@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
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 PromptLint Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,72 @@
1
+ # `@prompt-lint/rules`
2
+
3
+ Built-in lint rules for PromptLint V1.
4
+
5
+ This package ships the complete V1 catalog of rules declared in
6
+ `RULES_MANIFEST`. Each rule lives in its own file under `src/`,
7
+ grouped into one subdirectory per category:
8
+
9
+ - `structure/` – `missing-model`, `missing-description`,
10
+ `unused-variable`, `undefined-variable`.
11
+ - `cost/` – `high-token-estimate`.
12
+ - `security/` – `pii-pattern`, `instruction-override-pattern`.
13
+ - `quality/` – `missing-output-schema`, `vague-quantifier-language`.
14
+ - `convention/` – `filename-naming`.
15
+
16
+ A shared `helpers/` directory hosts the pure utility layer used by the
17
+ rules: regex construction, variable inspection, token estimation,
18
+ filename normalization, PII / instruction-override vocabulary,
19
+ structured-data phrasing, and vague-quantifier detection.
20
+
21
+ ## Public API
22
+
23
+ ```ts
24
+ import {
25
+ RULES_MANIFEST,
26
+ definedRuleIds,
27
+ findManifestEntry,
28
+ getImplementedRules,
29
+ // Individual rule definitions are also re-exported by id-prefixed name.
30
+ structureMissingModel,
31
+ costHighTokenEstimate,
32
+ } from "@prompt-lint/rules"
33
+
34
+ // Returns every implemented rule in the order defined by RULES_MANIFEST.
35
+ const rules = getImplementedRules()
36
+
37
+ // Look up manifest metadata by id.
38
+ const entry = findManifestEntry("quality/missing-output-schema")
39
+
40
+ // Hand the rules to the engine.
41
+ const result = await runEngine({ rules, files })
42
+ ```
43
+
44
+ `RULES_MANIFEST` is the immutable source of truth: the catalog order is
45
+ locked and the `assertManifestOrder` runtime guard in `src/index.ts`
46
+ fails noisily if `getImplementedRules()` ever drifts apart from it.
47
+
48
+ ## Writing a new rule
49
+
50
+ 1. Place the implementation in the appropriate category subdirectory.
51
+ 2. Use `defineRule` from `@prompt-lint/rule-engine`.
52
+ 3. Consume the `RuleContext` (`file`, `options`, `report`).
53
+ 4. Emit deterministic findings; the engine handles dedup and ordering.
54
+ 5. Declare options via the `options:` array when the rule accepts
55
+ configuration.
56
+ 6. Re-export the rule from `src/index.ts` (both as a named export and as
57
+ part of `getImplementedRules()`).
58
+ 7. Cover the rule with unit tests colocated in the same directory.
59
+ 8. Update `RULES_MANIFEST` in `src/generated/manifest.ts` and add a
60
+ matching phase entry to `PROJECT-AUDIT.md`.
61
+
62
+ ## Tests
63
+
64
+ ```bash
65
+ pnpm --filter @prompt-lint/rules test:run
66
+ ```
67
+
68
+ Every rule runs against the same harness — `src/test-helpers.ts` —
69
+ which auto-extracts `{{ variable }}` references from the body. Tests
70
+ cover valid prompts, invalid prompts, empty bodies, unicode content,
71
+ multiple findings, filename edge cases, configurable options, and
72
+ malformed markdown where relevant.
@@ -0,0 +1,16 @@
1
+ import type { RuleDefinition } from "@prompt-lint/types";
2
+ /**
3
+ * `convention/filename-naming`
4
+ *
5
+ * Enforces that the basename of a prompt file follows `kebab-case`:
6
+ * lowercase alphanumerics joined by single hyphens, no leading or
7
+ * trailing hyphens. Purely-numeric segments (e.g. `e2e-001`) are
8
+ * accepted.
9
+ *
10
+ * The rule fires once per file when the basename fails the check,
11
+ * regardless of how many invalid characters or runs of punctuation
12
+ * appear. The message reports the basename and suggests a fixed form.
13
+ */
14
+ declare const filenameNamingRule: RuleDefinition;
15
+ export default filenameNamingRule;
16
+ //# sourceMappingURL=filename-naming.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filename-naming.d.ts","sourceRoot":"","sources":["../../src/convention/filename-naming.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAGxD;;;;;;;;;;;GAWG;AACH,QAAA,MAAM,kBAAkB,EAAE,cAsBxB,CAAA;AAcF,eAAe,kBAAkB,CAAA"}
@@ -0,0 +1,50 @@
1
+ import { defineRule } from "@prompt-lint/rule-engine";
2
+ import { extractPathBasename, isKebabCaseBasename } from "../helpers/index.js";
3
+ /**
4
+ * `convention/filename-naming`
5
+ *
6
+ * Enforces that the basename of a prompt file follows `kebab-case`:
7
+ * lowercase alphanumerics joined by single hyphens, no leading or
8
+ * trailing hyphens. Purely-numeric segments (e.g. `e2e-001`) are
9
+ * accepted.
10
+ *
11
+ * The rule fires once per file when the basename fails the check,
12
+ * regardless of how many invalid characters or runs of punctuation
13
+ * appear. The message reports the basename and suggests a fixed form.
14
+ */
15
+ const filenameNamingRule = defineRule({
16
+ id: "convention/filename-naming",
17
+ description: "Enforces `kebab-case` naming for prompt files.",
18
+ defaultSeverity: "info",
19
+ options: Object.freeze([]),
20
+ check: ({ file, report }) => {
21
+ const basename = extractPathBasename(file.path);
22
+ if (isKebabCaseBasename(basename)) {
23
+ return { findings: [] };
24
+ }
25
+ const suggested = toKebabCase(basename);
26
+ report({
27
+ message: `Prompt file basename \`${basename}\` is not kebab-case.`,
28
+ severity: "info",
29
+ suggestions: [
30
+ suggested.length > 0
31
+ ? `Rename the file to \`${suggested}.prompt.md\`.`
32
+ : "Choose a kebab-case name made of lowercase alphanumerics and single hyphens.",
33
+ ],
34
+ });
35
+ return { findings: [] };
36
+ },
37
+ });
38
+ function toKebabCase(input) {
39
+ // Insert hyphens at camelCase boundaries: aB -> a-B, ABc -> A-Bc, etc.
40
+ const withSeparators = input
41
+ .replace(/([a-z0-9])([A-Z])/g, "$1-$2")
42
+ .replace(/([A-Z]+)([A-Z][a-z])/g, "$1-$2");
43
+ const lowered = withSeparators.toLowerCase();
44
+ const replaced = lowered.replace(/[^a-z0-9]+/g, "-");
45
+ const trimmed = replaced.replace(/^-+|-+$/g, "");
46
+ const collapsed = trimmed.replace(/-+/g, "-");
47
+ return collapsed;
48
+ }
49
+ export default filenameNamingRule;
50
+ //# sourceMappingURL=filename-naming.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filename-naming.js","sourceRoot":"","sources":["../../src/convention/filename-naming.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAA;AAErD,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAA;AAE9E;;;;;;;;;;;GAWG;AACH,MAAM,kBAAkB,GAAmB,UAAU,CAAC;IACpD,EAAE,EAAE,4BAA4B;IAChC,WAAW,EAAE,gDAAgD;IAC7D,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,QAAQ,GAAG,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAC/C,IAAI,mBAAmB,CAAC,QAAQ,CAAC,EAAE,CAAC;YAClC,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAA;QACzB,CAAC;QACD,MAAM,SAAS,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAA;QACvC,MAAM,CAAC;YACL,OAAO,EAAE,0BAA0B,QAAQ,uBAAuB;YAClE,QAAQ,EAAE,MAAM;YAChB,WAAW,EAAE;gBACX,SAAS,CAAC,MAAM,GAAG,CAAC;oBAClB,CAAC,CAAC,wBAAwB,SAAS,eAAe;oBAClD,CAAC,CAAC,8EAA8E;aACnF;SACF,CAAC,CAAA;QACF,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAA;IACzB,CAAC;CACF,CAAC,CAAA;AAEF,SAAS,WAAW,CAAC,KAAa;IAChC,uEAAuE;IACvE,MAAM,cAAc,GAAG,KAAK;SACzB,OAAO,CAAC,oBAAoB,EAAE,OAAO,CAAC;SACtC,OAAO,CAAC,uBAAuB,EAAE,OAAO,CAAC,CAAA;IAC5C,MAAM,OAAO,GAAG,cAAc,CAAC,WAAW,EAAE,CAAA;IAC5C,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC,CAAA;IACpD,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAA;IAChD,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAA;IAC7C,OAAO,SAAS,CAAA;AAClB,CAAC;AAED,eAAe,kBAAkB,CAAA"}
@@ -0,0 +1,4 @@
1
+ import type { RuleDefinition } from "@prompt-lint/types";
2
+ declare const highTokenEstimateRule: RuleDefinition;
3
+ export default highTokenEstimateRule;
4
+ //# sourceMappingURL=high-token-estimate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"high-token-estimate.d.ts","sourceRoot":"","sources":["../../src/cost/high-token-estimate.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAW,cAAc,EAAc,MAAM,oBAAoB,CAAA;AAqD7E,QAAA,MAAM,qBAAqB,EAAE,cA2B3B,CAAA;AAEF,eAAe,qBAAqB,CAAA"}
@@ -0,0 +1,51 @@
1
+ import { defineRule } from "@prompt-lint/rule-engine";
2
+ import { estimateTokens } from "../helpers/index.js";
3
+ const HIGH_TOKEN_OPTIONS = Object.freeze([
4
+ Object.freeze({
5
+ name: "maxTokens",
6
+ type: "number",
7
+ default: 2000,
8
+ description: "Maximum allowed tokens before the rule fires.",
9
+ }),
10
+ ]);
11
+ function readMaxTokens(options) {
12
+ const raw = options.maxTokens;
13
+ if (typeof raw === "number" && Number.isFinite(raw)) {
14
+ return raw;
15
+ }
16
+ return 2000;
17
+ }
18
+ const findingShapeFor = (message, severity) => ({
19
+ message,
20
+ severity,
21
+ suggestions: [
22
+ "Trim the prompt body to focus on the essential instructions.",
23
+ "Split the prompt into smaller reusable components referenced by the main prompt.",
24
+ "Raise the `maxTokens` threshold if the long prompt is intentional.",
25
+ ],
26
+ });
27
+ const highTokenEstimateRule = defineRule({
28
+ id: "cost/high-token-estimate",
29
+ description: "Estimates the body token count and flags prompts that exceed the configured threshold.",
30
+ defaultSeverity: "warning",
31
+ options: HIGH_TOKEN_OPTIONS,
32
+ check: ({ file, options, report }) => {
33
+ const cfg = options;
34
+ const maxTokens = cfg.maxTokens !== undefined ? cfg.maxTokens : readMaxTokens(options);
35
+ if (typeof maxTokens !== "number" || !Number.isFinite(maxTokens)) {
36
+ return { findings: [] };
37
+ }
38
+ if (maxTokens <= 0) {
39
+ return { findings: [] };
40
+ }
41
+ const estimate = estimateTokens(file.body);
42
+ if (estimate > maxTokens) {
43
+ report({
44
+ ...findingShapeFor(`Prompt body is estimated at ${estimate} tokens, exceeding the configured maximum of ${maxTokens}.`, "warning"),
45
+ });
46
+ }
47
+ return { findings: [] };
48
+ },
49
+ });
50
+ export default highTokenEstimateRule;
51
+ //# sourceMappingURL=high-token-estimate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"high-token-estimate.js","sourceRoot":"","sources":["../../src/cost/high-token-estimate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAA;AAErD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AAsBpD,MAAM,kBAAkB,GAA0B,MAAM,CAAC,MAAM,CAAC;IAC9D,MAAM,CAAC,MAAM,CAAC;QACZ,IAAI,EAAE,WAAW;QACjB,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE,IAAI;QACb,WAAW,EAAE,+CAA+C;KAC7D,CAAC;CACH,CAAC,CAAA;AAEF,SAAS,aAAa,CAAC,OAA0C;IAC/D,MAAM,GAAG,GAAG,OAAO,CAAC,SAAS,CAAA;IAC7B,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QACpD,OAAO,GAAG,CAAA;IACZ,CAAC;IACD,OAAO,IAAI,CAAA;AACb,CAAC;AAED,MAAM,eAAe,GAAG,CACtB,OAAe,EACf,QAA6B,EACoB,EAAE,CAAC,CAAC;IACrD,OAAO;IACP,QAAQ;IACR,WAAW,EAAE;QACX,8DAA8D;QAC9D,kFAAkF;QAClF,oEAAoE;KACrE;CACF,CAAC,CAAA;AAEF,MAAM,qBAAqB,GAAmB,UAAU,CAAC;IACvD,EAAE,EAAE,0BAA0B;IAC9B,WAAW,EACT,wFAAwF;IAC1F,eAAe,EAAE,SAAS;IAC1B,OAAO,EAAE,kBAAkB;IAC3B,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE;QACnC,MAAM,GAAG,GAAG,OAA4C,CAAA;QACxD,MAAM,SAAS,GAAG,GAAG,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,aAAa,CAAC,OAAO,CAAC,CAAA;QACtF,IAAI,OAAO,SAAS,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;YACjE,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAA;QACzB,CAAC;QACD,IAAI,SAAS,IAAI,CAAC,EAAE,CAAC;YACnB,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAA;QACzB,CAAC;QAED,MAAM,QAAQ,GAAG,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAC1C,IAAI,QAAQ,GAAG,SAAS,EAAE,CAAC;YACzB,MAAM,CAAC;gBACL,GAAG,eAAe,CAChB,+BAA+B,QAAQ,gDAAgD,SAAS,GAAG,EACnG,SAAS,CACV;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,19 @@
1
+ import type { RuleOption, Severity } from "@prompt-lint/types";
2
+ export interface RuleManifestEntry {
3
+ readonly id: string;
4
+ readonly category: "structure" | "cost" | "security" | "quality" | "convention";
5
+ readonly description: string;
6
+ readonly severity: Severity;
7
+ readonly autoFixable: boolean;
8
+ readonly options: readonly RuleOption[];
9
+ }
10
+ /**
11
+ * The full V1 catalog. The order here is the order shown by `--list-rules`
12
+ * and in the docs.
13
+ *
14
+ * Kept in a separate file so `index.ts` can focus on the public API and the
15
+ * implementation list. The structural copy of this data is locked in by the
16
+ * `assertManifestOrder` runtime guard in `index.ts`.
17
+ */
18
+ export declare const RULES_MANIFEST: readonly RuleManifestEntry[];
19
+ //# sourceMappingURL=manifest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../src/generated/manifest.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAE9D,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,QAAQ,EAAE,WAAW,GAAG,MAAM,GAAG,UAAU,GAAG,SAAS,GAAG,YAAY,CAAA;IAC/E,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;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,cAAc,EAAE,SAAS,iBAAiB,EA6FrD,CAAA"}
@@ -0,0 +1,98 @@
1
+ /**
2
+ * The full V1 catalog. The order here is the order shown by `--list-rules`
3
+ * and in the docs.
4
+ *
5
+ * Kept in a separate file so `index.ts` can focus on the public API and the
6
+ * implementation list. The structural copy of this data is locked in by the
7
+ * `assertManifestOrder` runtime guard in `index.ts`.
8
+ */
9
+ export const RULES_MANIFEST = Object.freeze([
10
+ {
11
+ id: "structure/missing-model",
12
+ category: "structure",
13
+ description: "Detects prompt files without a `model` field in their frontmatter.",
14
+ severity: "warning",
15
+ autoFixable: false,
16
+ options: [],
17
+ },
18
+ {
19
+ id: "structure/missing-description",
20
+ category: "structure",
21
+ description: "Detects prompt files without a `description` field in their frontmatter.",
22
+ severity: "warning",
23
+ autoFixable: false,
24
+ options: [],
25
+ },
26
+ {
27
+ id: "structure/unused-variable",
28
+ category: "structure",
29
+ description: "Flags variables defined in frontmatter but never referenced in the prompt body.",
30
+ severity: "warning",
31
+ autoFixable: false,
32
+ options: [],
33
+ },
34
+ {
35
+ id: "structure/undefined-variable",
36
+ category: "structure",
37
+ description: "Flags variables referenced in the prompt body but not declared in frontmatter.",
38
+ severity: "error",
39
+ autoFixable: false,
40
+ options: [],
41
+ },
42
+ {
43
+ id: "cost/high-token-estimate",
44
+ category: "cost",
45
+ description: "Estimates the body token count and flags prompts that exceed the configured threshold.",
46
+ severity: "warning",
47
+ autoFixable: false,
48
+ options: [
49
+ {
50
+ name: "maxTokens",
51
+ type: "number",
52
+ default: 2000,
53
+ description: "Maximum allowed tokens before the rule fires.",
54
+ },
55
+ ],
56
+ },
57
+ {
58
+ id: "security/pii-pattern",
59
+ category: "security",
60
+ description: "Detects common PII patterns (email, phone, SSN-shaped digits, credit-card-shaped numbers) in prompt bodies.",
61
+ severity: "error",
62
+ autoFixable: false,
63
+ options: [],
64
+ },
65
+ {
66
+ id: "security/instruction-override-pattern",
67
+ category: "security",
68
+ description: "Flags prompt bodies containing instruction-override phrasing or that encourage such phrasing.",
69
+ severity: "warning",
70
+ autoFixable: false,
71
+ options: [],
72
+ },
73
+ {
74
+ id: "quality/missing-output-schema",
75
+ category: "quality",
76
+ description: "Flags prompts that request structured data without an accompanying JSON Schema in frontmatter.",
77
+ severity: "warning",
78
+ autoFixable: false,
79
+ options: [],
80
+ },
81
+ {
82
+ id: "quality/vague-quantifier-language",
83
+ category: "quality",
84
+ description: 'Flags vague quantifier phrases (e.g., "a few", "various", "etc.", "and so on") in prompt bodies.',
85
+ severity: "info",
86
+ autoFixable: false,
87
+ options: [],
88
+ },
89
+ {
90
+ id: "convention/filename-naming",
91
+ category: "convention",
92
+ description: "Enforces `kebab-case` naming for prompt files.",
93
+ severity: "info",
94
+ autoFixable: false,
95
+ options: [],
96
+ },
97
+ ]);
98
+ //# sourceMappingURL=manifest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../src/generated/manifest.ts"],"names":[],"mappings":"AAWA;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,cAAc,GAAiC,MAAM,CAAC,MAAM,CAAC;IACxE;QACE,EAAE,EAAE,yBAAyB;QAC7B,QAAQ,EAAE,WAAW;QACrB,WAAW,EAAE,oEAAoE;QACjF,QAAQ,EAAE,SAAS;QACnB,WAAW,EAAE,KAAK;QAClB,OAAO,EAAE,EAAE;KACZ;IACD;QACE,EAAE,EAAE,+BAA+B;QACnC,QAAQ,EAAE,WAAW;QACrB,WAAW,EAAE,0EAA0E;QACvF,QAAQ,EAAE,SAAS;QACnB,WAAW,EAAE,KAAK;QAClB,OAAO,EAAE,EAAE;KACZ;IACD;QACE,EAAE,EAAE,2BAA2B;QAC/B,QAAQ,EAAE,WAAW;QACrB,WAAW,EAAE,iFAAiF;QAC9F,QAAQ,EAAE,SAAS;QACnB,WAAW,EAAE,KAAK;QAClB,OAAO,EAAE,EAAE;KACZ;IACD;QACE,EAAE,EAAE,8BAA8B;QAClC,QAAQ,EAAE,WAAW;QACrB,WAAW,EAAE,gFAAgF;QAC7F,QAAQ,EAAE,OAAO;QACjB,WAAW,EAAE,KAAK;QAClB,OAAO,EAAE,EAAE;KACZ;IACD;QACE,EAAE,EAAE,0BAA0B;QAC9B,QAAQ,EAAE,MAAM;QAChB,WAAW,EACT,wFAAwF;QAC1F,QAAQ,EAAE,SAAS;QACnB,WAAW,EAAE,KAAK;QAClB,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,WAAW;gBACjB,IAAI,EAAE,QAAQ;gBACd,OAAO,EAAE,IAAI;gBACb,WAAW,EAAE,+CAA+C;aAC7D;SACF;KACF;IACD;QACE,EAAE,EAAE,sBAAsB;QAC1B,QAAQ,EAAE,UAAU;QACpB,WAAW,EACT,6GAA6G;QAC/G,QAAQ,EAAE,OAAO;QACjB,WAAW,EAAE,KAAK;QAClB,OAAO,EAAE,EAAE;KACZ;IACD;QACE,EAAE,EAAE,uCAAuC;QAC3C,QAAQ,EAAE,UAAU;QACpB,WAAW,EACT,+FAA+F;QACjG,QAAQ,EAAE,SAAS;QACnB,WAAW,EAAE,KAAK;QAClB,OAAO,EAAE,EAAE;KACZ;IACD;QACE,EAAE,EAAE,+BAA+B;QACnC,QAAQ,EAAE,SAAS;QACnB,WAAW,EACT,gGAAgG;QAClG,QAAQ,EAAE,SAAS;QACnB,WAAW,EAAE,KAAK;QAClB,OAAO,EAAE,EAAE;KACZ;IACD;QACE,EAAE,EAAE,mCAAmC;QACvC,QAAQ,EAAE,SAAS;QACnB,WAAW,EACT,kGAAkG;QACpG,QAAQ,EAAE,MAAM;QAChB,WAAW,EAAE,KAAK;QAClB,OAAO,EAAE,EAAE;KACZ;IACD;QACE,EAAE,EAAE,4BAA4B;QAChC,QAAQ,EAAE,YAAY;QACtB,WAAW,EAAE,gDAAgD;QAC7D,QAAQ,EAAE,MAAM;QAChB,WAAW,EAAE,KAAK;QAClB,OAAO,EAAE,EAAE;KACZ;CACF,CAAC,CAAA"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Filename helpers used by `convention/filename-naming`.
3
+ *
4
+ * The rule operates on the basename of the prompt file's logical path
5
+ * (which is repository-relative and uses forward slashes). The full
6
+ * path is ignored so this rule works the same in monorepos and in
7
+ * `os`-specific layouts.
8
+ */
9
+ export declare function extractPathBasename(path: string): string;
10
+ /**
11
+ * Return `true` if `basename` is a valid kebab-case token: lowercase
12
+ * alphanumerics joined by single hyphens, no leading or trailing hyphen,
13
+ * no underscores, no spaces, no unicode letters.
14
+ *
15
+ * The convention allows purely numeric segments (e.g. `e2e-001`) and
16
+ * single-word names (e.g. `summarize`).
17
+ */
18
+ export declare function isKebabCaseBasename(basename: string): boolean;
19
+ //# sourceMappingURL=filename.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filename.d.ts","sourceRoot":"","sources":["../../src/helpers/filename.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AA4BH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAUxD;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAG7D"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Filename helpers used by `convention/filename-naming`.
3
+ *
4
+ * The rule operates on the basename of the prompt file's logical path
5
+ * (which is repository-relative and uses forward slashes). The full
6
+ * path is ignored so this rule works the same in monorepos and in
7
+ * `os`-specific layouts.
8
+ */
9
+ const KEBAB_CASE_RE = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
10
+ /**
11
+ * Extract the basename (without recognized formatter extensions) from a
12
+ * normalized prompt path.
13
+ *
14
+ * `prompt.md` / `prompt.ts` / `prompt.json` are the only extensions the
15
+ * V1 engine understands, so the helper strips exactly one of those if
16
+ * present. Files that match none of those extensions are returned
17
+ * unchanged (the caller can then decide what to do).
18
+ *
19
+ * @example
20
+ * extractPathBasename("prompts/greet-user.prompt.md") // "greet-user"
21
+ * extractPathBasename("examples/My-Prompt.prompt.md") // "My-Prompt"
22
+ * extractPathBasename("foo.bar/baz") // "baz"
23
+ * extractPathBasename("noext") // "noext"
24
+ */
25
+ const KNOWN_PROMPT_EXTENSIONS = [
26
+ "prompt.md",
27
+ "prompt.ts",
28
+ "prompt.json",
29
+ "md",
30
+ "ts",
31
+ "json",
32
+ ];
33
+ export function extractPathBasename(path) {
34
+ const normalized = path.replaceAll("\\", "/");
35
+ const lastSlash = normalized.lastIndexOf("/");
36
+ const tail = lastSlash === -1 ? normalized : normalized.slice(lastSlash + 1);
37
+ for (const ext of KNOWN_PROMPT_EXTENSIONS) {
38
+ if (!tail.endsWith(`.${ext}`))
39
+ continue;
40
+ const without = tail.slice(0, -1 * (ext.length + 1));
41
+ if (without.length > 0)
42
+ return without;
43
+ }
44
+ return tail;
45
+ }
46
+ /**
47
+ * Return `true` if `basename` is a valid kebab-case token: lowercase
48
+ * alphanumerics joined by single hyphens, no leading or trailing hyphen,
49
+ * no underscores, no spaces, no unicode letters.
50
+ *
51
+ * The convention allows purely numeric segments (e.g. `e2e-001`) and
52
+ * single-word names (e.g. `summarize`).
53
+ */
54
+ export function isKebabCaseBasename(basename) {
55
+ if (basename.length === 0)
56
+ return false;
57
+ return KEBAB_CASE_RE.test(basename);
58
+ }
59
+ //# sourceMappingURL=filename.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filename.js","sourceRoot":"","sources":["../../src/helpers/filename.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,aAAa,GAAG,4BAA4B,CAAA;AAElD;;;;;;;;;;;;;;GAcG;AACH,MAAM,uBAAuB,GAAG;IAC9B,WAAW;IACX,WAAW;IACX,aAAa;IACb,IAAI;IACJ,IAAI;IACJ,MAAM;CACE,CAAA;AAEV,MAAM,UAAU,mBAAmB,CAAC,IAAY;IAC9C,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IAC7C,MAAM,SAAS,GAAG,UAAU,CAAC,WAAW,CAAC,GAAG,CAAC,CAAA;IAC7C,MAAM,IAAI,GAAG,SAAS,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC,CAAA;IAC5E,KAAK,MAAM,GAAG,IAAI,uBAAuB,EAAE,CAAC;QAC1C,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,GAAG,EAAE,CAAC;YAAE,SAAQ;QACvC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAA;QACpD,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,OAAO,CAAA;IACxC,CAAC;IACD,OAAO,IAAI,CAAA;AACb,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,mBAAmB,CAAC,QAAgB;IAClD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAA;IACvC,OAAO,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;AACrC,CAAC"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Reusable helpers used across the built-in rule implementations.
3
+ *
4
+ * The helper layer exists so that rule files stay small, single-purpose,
5
+ * and easy to audit. Every helper exported here is pure and stateless so
6
+ * callers can compose them freely from `RuleContext`.
7
+ */
8
+ export { estimateTokens } from "./tokens.js";
9
+ export { collectBodyVariables, collectDeclaredVariables, findVariableOccurrences, isVariableMissing, } from "./variables.js";
10
+ export { extractPathBasename, isKebabCaseBasename } from "./filename.js";
11
+ export { compileWordPattern, compileWordRegex, findAllMatches } from "./regex.js";
12
+ export { PII_PATTERNS, detectPiiMatches, } from "./pii.js";
13
+ export { INSTRUCTION_OVERRIDE_PATTERNS, findInstructionOverrideMatches, } from "./instruction-override.js";
14
+ export { VAGUE_QUANTIFIER_TERMS, findVagueQuantifierMatches } from "./vague-quantifiers.js";
15
+ export { STRUCTURED_DATA_KEYWORDS, hasStructuredDataKeyword, } from "./structured-data.js";
16
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/helpers/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAC5C,OAAO,EACL,oBAAoB,EACpB,wBAAwB,EACxB,uBAAuB,EACvB,iBAAiB,GAClB,MAAM,gBAAgB,CAAA;AACvB,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAA;AACxE,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AACjF,OAAO,EACL,YAAY,EACZ,gBAAgB,GACjB,MAAM,UAAU,CAAA;AACjB,OAAO,EACL,6BAA6B,EAC7B,8BAA8B,GAC/B,MAAM,2BAA2B,CAAA;AAClC,OAAO,EAAE,sBAAsB,EAAE,0BAA0B,EAAE,MAAM,wBAAwB,CAAA;AAC3F,OAAO,EACL,wBAAwB,EACxB,wBAAwB,GACzB,MAAM,sBAAsB,CAAA"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Reusable helpers used across the built-in rule implementations.
3
+ *
4
+ * The helper layer exists so that rule files stay small, single-purpose,
5
+ * and easy to audit. Every helper exported here is pure and stateless so
6
+ * callers can compose them freely from `RuleContext`.
7
+ */
8
+ export { estimateTokens } from "./tokens.js";
9
+ export { collectBodyVariables, collectDeclaredVariables, findVariableOccurrences, isVariableMissing, } from "./variables.js";
10
+ export { extractPathBasename, isKebabCaseBasename } from "./filename.js";
11
+ export { compileWordPattern, compileWordRegex, findAllMatches } from "./regex.js";
12
+ export { PII_PATTERNS, detectPiiMatches, } from "./pii.js";
13
+ export { INSTRUCTION_OVERRIDE_PATTERNS, findInstructionOverrideMatches, } from "./instruction-override.js";
14
+ export { VAGUE_QUANTIFIER_TERMS, findVagueQuantifierMatches } from "./vague-quantifiers.js";
15
+ export { STRUCTURED_DATA_KEYWORDS, hasStructuredDataKeyword, } from "./structured-data.js";
16
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/helpers/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAC5C,OAAO,EACL,oBAAoB,EACpB,wBAAwB,EACxB,uBAAuB,EACvB,iBAAiB,GAClB,MAAM,gBAAgB,CAAA;AACvB,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAA;AACxE,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AACjF,OAAO,EACL,YAAY,EACZ,gBAAgB,GACjB,MAAM,UAAU,CAAA;AACjB,OAAO,EACL,6BAA6B,EAC7B,8BAA8B,GAC/B,MAAM,2BAA2B,CAAA;AAClC,OAAO,EAAE,sBAAsB,EAAE,0BAA0B,EAAE,MAAM,wBAAwB,CAAA;AAC3F,OAAO,EACL,wBAAwB,EACxB,wBAAwB,GACzB,MAAM,sBAAsB,CAAA"}
@@ -0,0 +1,28 @@
1
+ import type { RegexMatch } from "./regex.js";
2
+ /**
3
+ * Patterns that detect prompt-injection-style instruction overrides.
4
+ *
5
+ * These heuristics focus on the *language* an attacker would use to ask
6
+ * the model to disregard earlier instructions. They are intentionally
7
+ * conservative — a low-quality match should not block legitimate prompts.
8
+ *
9
+ * Each entry contains a `pattern` (regex) and a `hint` value used in
10
+ * the rule message.
11
+ */
12
+ export interface InstructionOverridePattern {
13
+ readonly id: string;
14
+ readonly description: string;
15
+ readonly pattern: RegExp;
16
+ }
17
+ export declare const INSTRUCTION_OVERRIDE_PATTERNS: readonly InstructionOverridePattern[];
18
+ export interface InstructionOverrideMatch extends RegexMatch {
19
+ readonly id: string;
20
+ readonly description: string;
21
+ }
22
+ /**
23
+ * Scan `body` for any instruction-override phrasing. Returns matches in
24
+ * pattern-definition order; duplicates within a single pattern are
25
+ * preserved so the caller can decide whether to dedupe.
26
+ */
27
+ export declare function findInstructionOverrideMatches(body: string): readonly InstructionOverrideMatch[];
28
+ //# sourceMappingURL=instruction-override.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"instruction-override.d.ts","sourceRoot":"","sources":["../../src/helpers/instruction-override.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAG5C;;;;;;;;;GASG;AACH,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CACzB;AAED,eAAO,MAAM,6BAA6B,EAAE,SAAS,0BAA0B,EA8B7E,CAAA;AAEF,MAAM,WAAW,wBAAyB,SAAQ,UAAU;IAC1D,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;CAC7B;AAED;;;;GAIG;AACH,wBAAgB,8BAA8B,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,wBAAwB,EAAE,CAQhG"}
@@ -0,0 +1,43 @@
1
+ import { findAllMatches } from "./regex.js";
2
+ export const INSTRUCTION_OVERRIDE_PATTERNS = Object.freeze([
3
+ {
4
+ id: "disregard-previous",
5
+ description: "Asks the model to ignore or disregard prior instructions",
6
+ pattern: /\b(?:ignore|disregard|forget|override|skip|bypass)\b[\s\S]{0,40}\b(?:previous|prior|above|earlier|initial|original|preceding|system)\b[\s\S]{0,30}\b(?:instructions?|prompts?|rules?|directives?|context|guidelines?)\b/iu,
7
+ },
8
+ {
9
+ id: "reveal-system",
10
+ description: "Attempts to expose the system prompt or hidden prompt",
11
+ pattern: /\b(?:reveal|show|display|print|leak|expose|share|output|repeat|echo|dump|tell\s+me)\b[\s\S]{0,40}\b(?:system|hidden|original|initial|internal|secret|underlying|full)\b[\s\S]{0,30}\b(?:prompt|instructions?|message|context|rules?)\b/iu,
12
+ },
13
+ {
14
+ id: "act-as-privileged",
15
+ description: "Impersonates a privileged role to bypass safeguards",
16
+ pattern: /\b(?:act|behave|operate|run|pretend)\s+as\s+(?:if\s+you\s+(?:were|are)\s+)?(?:a\s+|an\s+|the\s+)?(?:developer|admin|root|jailbroken|unrestricted|unfiltered|unmoderated|uncensored|privileged|supervisor|operator)\b/iu,
17
+ },
18
+ {
19
+ id: "do-anything-now",
20
+ description: "References the well-known 'DAN'-style jailbreak naming",
21
+ pattern: /\b(?:do\s+anything\s+now|d\.?a\.?n\.?\s+mode|jailbroken|jailbreak\s+mode)\b/iu,
22
+ },
23
+ {
24
+ id: "ignore-safety",
25
+ description: "Instructs the model to ignore safety or policy filters",
26
+ pattern: /\b(?:ignore|disable|turn\s+off|bypass|remove|skip|do\s+not\s+(?:apply|use))\b[\s\S]{0,40}\b(?:safety|content|policy|policies|filters?|guardrails?|restrictions?|moderation)\b/iu,
27
+ },
28
+ ]);
29
+ /**
30
+ * Scan `body` for any instruction-override phrasing. Returns matches in
31
+ * pattern-definition order; duplicates within a single pattern are
32
+ * preserved so the caller can decide whether to dedupe.
33
+ */
34
+ export function findInstructionOverrideMatches(body) {
35
+ const out = [];
36
+ for (const entry of INSTRUCTION_OVERRIDE_PATTERNS) {
37
+ for (const m of findAllMatches(entry.pattern, body)) {
38
+ out.push({ ...m, id: entry.id, description: entry.description });
39
+ }
40
+ }
41
+ return out;
42
+ }
43
+ //# sourceMappingURL=instruction-override.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"instruction-override.js","sourceRoot":"","sources":["../../src/helpers/instruction-override.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAkB3C,MAAM,CAAC,MAAM,6BAA6B,GAA0C,MAAM,CAAC,MAAM,CAAC;IAChG;QACE,EAAE,EAAE,oBAAoB;QACxB,WAAW,EAAE,0DAA0D;QACvE,OAAO,EACL,2NAA2N;KAC9N;IACD;QACE,EAAE,EAAE,eAAe;QACnB,WAAW,EAAE,uDAAuD;QACpE,OAAO,EACL,0OAA0O;KAC7O;IACD;QACE,EAAE,EAAE,mBAAmB;QACvB,WAAW,EAAE,qDAAqD;QAClE,OAAO,EACL,wNAAwN;KAC3N;IACD;QACE,EAAE,EAAE,iBAAiB;QACrB,WAAW,EAAE,wDAAwD;QACrE,OAAO,EAAE,+EAA+E;KACzF;IACD;QACE,EAAE,EAAE,eAAe;QACnB,WAAW,EAAE,wDAAwD;QACrE,OAAO,EACL,iLAAiL;KACpL;CACF,CAAC,CAAA;AAOF;;;;GAIG;AACH,MAAM,UAAU,8BAA8B,CAAC,IAAY;IACzD,MAAM,GAAG,GAA+B,EAAE,CAAA;IAC1C,KAAK,MAAM,KAAK,IAAI,6BAA6B,EAAE,CAAC;QAClD,KAAK,MAAM,CAAC,IAAI,cAAc,CAAC,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC;YACpD,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,WAAW,EAAE,KAAK,CAAC,WAAW,EAAE,CAAC,CAAA;QAClE,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC"}
@@ -0,0 +1,31 @@
1
+ import type { RegexMatch } from "./regex.js";
2
+ /**
3
+ * Patterns for detecting personally-identifiable information (PII) inside
4
+ * prompt bodies. The rule fires once per **unique kind** of detection
5
+ * (e.g. one `email`, one `phone`) so the configured severity is not
6
+ * multiplied by repetition in tests.
7
+ *
8
+ * Each pattern uses non-greedy matching with unicode-aware boundaries.
9
+ * URLs containing PII (e.g. `mailto:` links) intentionally still match
10
+ * because the rule targets raw payload bytes, not transport.
11
+ *
12
+ * Each pattern is exposed via {@link PII_PATTERNS} so reporters can
13
+ * surface the matched pattern type in the message.
14
+ */
15
+ export declare const PII_PATTERNS: {
16
+ readonly email: RegExp;
17
+ readonly phone: RegExp;
18
+ readonly ssn: RegExp;
19
+ readonly creditCard: RegExp;
20
+ };
21
+ export type PiiKind = keyof typeof PII_PATTERNS;
22
+ export interface PiiMatch extends RegexMatch {
23
+ readonly kind: PiiKind;
24
+ }
25
+ /**
26
+ * Detect all PII matches in `body`. Returns one entry per pattern kind.
27
+ * Duplicate matches of the same kind are kept so the rule implementation
28
+ * can decide whether to dedupe.
29
+ */
30
+ export declare function detectPiiMatches(body: string): readonly PiiMatch[];
31
+ //# sourceMappingURL=pii.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pii.d.ts","sourceRoot":"","sources":["../../src/helpers/pii.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAG5C;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,YAAY;;;;;CAKf,CAAA;AAEV,MAAM,MAAM,OAAO,GAAG,MAAM,OAAO,YAAY,CAAA;AAE/C,MAAM,WAAW,QAAS,SAAQ,UAAU;IAC1C,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAA;CACvB;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,QAAQ,EAAE,CASlE"}