@agllama/mcp 0.6.27 → 0.7.1

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 (71) hide show
  1. package/README.md +56 -2
  2. package/SECURITY.md +62 -0
  3. package/dist/api-client.d.ts +34 -2
  4. package/dist/api-client.d.ts.map +1 -1
  5. package/dist/api-client.js +162 -60
  6. package/dist/api-client.js.map +1 -1
  7. package/dist/server.d.ts.map +1 -1
  8. package/dist/server.js +71 -1
  9. package/dist/server.js.map +1 -1
  10. package/dist/tools/__tests__/llama1876.test.d.ts +2 -0
  11. package/dist/tools/__tests__/llama1876.test.d.ts.map +1 -0
  12. package/dist/tools/__tests__/llama1876.test.js +311 -0
  13. package/dist/tools/__tests__/llama1876.test.js.map +1 -0
  14. package/dist/tools/__tests__/prScorer.test.d.ts +2 -0
  15. package/dist/tools/__tests__/prScorer.test.d.ts.map +1 -0
  16. package/dist/tools/__tests__/prScorer.test.js +537 -0
  17. package/dist/tools/__tests__/prScorer.test.js.map +1 -0
  18. package/dist/tools/__tests__/session.test.js +122 -2
  19. package/dist/tools/__tests__/session.test.js.map +1 -1
  20. package/dist/tools/context.js +2 -2
  21. package/dist/tools/context.js.map +1 -1
  22. package/dist/tools/devLinks.d.ts +5 -22
  23. package/dist/tools/devLinks.d.ts.map +1 -1
  24. package/dist/tools/devLinks.js +15 -110
  25. package/dist/tools/devLinks.js.map +1 -1
  26. package/dist/tools/epicSignOff.d.ts +25 -0
  27. package/dist/tools/epicSignOff.d.ts.map +1 -0
  28. package/dist/tools/epicSignOff.js +89 -0
  29. package/dist/tools/epicSignOff.js.map +1 -0
  30. package/dist/tools/help.d.ts.map +1 -1
  31. package/dist/tools/help.js +90 -2
  32. package/dist/tools/help.js.map +1 -1
  33. package/dist/tools/index.d.ts +4 -0
  34. package/dist/tools/index.d.ts.map +1 -1
  35. package/dist/tools/index.js +5 -1
  36. package/dist/tools/index.js.map +1 -1
  37. package/dist/tools/issueLinks.d.ts +10 -10
  38. package/dist/tools/issueLinks.d.ts.map +1 -1
  39. package/dist/tools/issueLinks.js +4 -4
  40. package/dist/tools/issueLinks.js.map +1 -1
  41. package/dist/tools/issues.d.ts +3 -0
  42. package/dist/tools/issues.d.ts.map +1 -1
  43. package/dist/tools/issues.js +26 -1
  44. package/dist/tools/issues.js.map +1 -1
  45. package/dist/tools/notificationRules.d.ts +2 -2
  46. package/dist/tools/prScorer.d.ts +41 -0
  47. package/dist/tools/prScorer.d.ts.map +1 -0
  48. package/dist/tools/prScorer.js +182 -0
  49. package/dist/tools/prScorer.js.map +1 -0
  50. package/dist/tools/prScorerHistory.d.ts +53 -0
  51. package/dist/tools/prScorerHistory.d.ts.map +1 -0
  52. package/dist/tools/prScorerHistory.js +251 -0
  53. package/dist/tools/prScorerHistory.js.map +1 -0
  54. package/dist/tools/prScorerSchema.d.ts +15 -0
  55. package/dist/tools/prScorerSchema.d.ts.map +1 -0
  56. package/dist/tools/prScorerSchema.js +262 -0
  57. package/dist/tools/prScorerSchema.js.map +1 -0
  58. package/dist/tools/roadmap.d.ts +5 -0
  59. package/dist/tools/roadmap.d.ts.map +1 -1
  60. package/dist/tools/roadmap.js +11 -2
  61. package/dist/tools/roadmap.js.map +1 -1
  62. package/dist/tools/session.d.ts +8 -0
  63. package/dist/tools/session.d.ts.map +1 -1
  64. package/dist/tools/session.js +18 -3
  65. package/dist/tools/session.js.map +1 -1
  66. package/dist/tools/sprints.d.ts.map +1 -1
  67. package/dist/tools/sprints.js +10 -0
  68. package/dist/tools/sprints.js.map +1 -1
  69. package/dist/types.d.ts +51 -1
  70. package/dist/types.d.ts.map +1 -1
  71. package/package.json +9 -4
@@ -27,6 +27,7 @@ export declare const manageNotificationRuleToolSchema: z.ZodObject<{
27
27
  projectId?: string | undefined;
28
28
  orgSlug?: string | undefined;
29
29
  description?: string | undefined;
30
+ assigneeIds?: string | undefined;
30
31
  name?: string | undefined;
31
32
  ruleId?: string | undefined;
32
33
  integrationId?: string | undefined;
@@ -36,7 +37,6 @@ export declare const manageNotificationRuleToolSchema: z.ZodObject<{
36
37
  deliveryConfig?: string | undefined;
37
38
  labelTriggers?: string | undefined;
38
39
  statusIds?: string | undefined;
39
- assigneeIds?: string | undefined;
40
40
  issueTypes?: string | undefined;
41
41
  priorities?: string | undefined;
42
42
  issueIds?: string | undefined;
@@ -47,6 +47,7 @@ export declare const manageNotificationRuleToolSchema: z.ZodObject<{
47
47
  projectId?: string | undefined;
48
48
  orgSlug?: string | undefined;
49
49
  description?: string | undefined;
50
+ assigneeIds?: string | undefined;
50
51
  name?: string | undefined;
51
52
  ruleId?: string | undefined;
52
53
  integrationId?: string | undefined;
@@ -56,7 +57,6 @@ export declare const manageNotificationRuleToolSchema: z.ZodObject<{
56
57
  deliveryConfig?: string | undefined;
57
58
  labelTriggers?: string | undefined;
58
59
  statusIds?: string | undefined;
59
- assigneeIds?: string | undefined;
60
60
  issueTypes?: string | undefined;
61
61
  priorities?: string | undefined;
62
62
  issueIds?: string | undefined;
@@ -0,0 +1,41 @@
1
+ import { z } from 'zod';
2
+ export declare const getPrScorerSchemaToolName = "llama_get_pr_scorer_schema";
3
+ export declare const getPrScorerSchemaToolDescription = "# PR Scorer Rule Language \u2014 Full DSL Reference\n\nPR Scorer rules let you automatically adjust the quality score of a pull\nrequest based on its content, metadata, and linked issues. Each rule is a\nsingle line that conditionally adds or subtracts points and optionally\nattaches a human-readable reason and flag label.\n\n---\n\n## Grammar (EBNF)\n\n```\nruleset := rule*\nrule := 'when' expr 'then' SignedInt ( 'reason' STRING )? ( 'flag' STRING )?\nSignedInt := ( '+' | '-' ) INTEGER // range: [-10, +10] inclusive\nSTRING := '\"' [^\"]* '\"'\n```\n\nBlank lines and lines beginning with `#` are treated as comments and are\nsilently ignored. Rules are evaluated in order; all matching rules fire\n(scores accumulate \u2014 there is no early-exit).\n\n### Hard limits\n\n| Constraint | Value |\n|---|---|\n| Maximum rules per ruleset | 100 |\n| Maximum nested any() / all() / count(lambda) depth | 8 |\n| Score per rule action | [-10, +10] |\n\n---\n\n## Evaluation Context \u2014 Variables\n\nEvery rule's `expr` can reference the following variables. All property\naccesses are null-safe: accessing a missing property returns `null` (which\nis falsy).\n\n### Top-level PR fields\n\n| Variable | Type | Description |\n|---|---|---|\n| `pr.id` | number | Pull request id (provider-native, e.g. ADO `pullRequestId`) |\n| `pr.title` | string | Pull request title |\n| `pr.description` | string | PR body / description |\n| `pr.author` | string | Display name (or unique name) of the PR author |\n| `pr.lastUpdated` | ISO-8601 string | Timestamp of last update |\n| `pr.isDraft` | boolean | `true` when the PR is in draft state |\n| `pr.filesChanged` | number | Total count of changed files in the PR |\n| `pr.commitCount` | number | Total count of commits in the PR |\n| `pr.linesAdded` | number \\| null | Aggregate lines added across the PR (null if the provider didn't return it) |\n| `pr.linesRemoved` | number \\| null | Aggregate lines removed across the PR (null if the provider didn't return it) |\n\n> The aggregate fields above are the cheapest signals for \"this PR is large.\"\n> Per-file line counts are not available from ADO, so prefer\n> `pr.filesChanged > 50` or `pr.linesAdded > 1000` over file-level thresholds.\n\n### Files\n\n`files` is an array of file-change objects.\n\n| Property | Type | Description |\n|---|---|---|\n| `path` | string | File path relative to repo root |\n| `additions` | number | Lines added in this file |\n| `deletions` | number | Lines deleted in this file |\n| `isBinary` | boolean | `true` if the file is binary |\n\nUse `files.length` or `files.count()` to count total changed files.\n\n> **Provider caveat (Azure DevOps):** the ADO `/stats` endpoint does not\n> return per-file line counts, so `additions` and `deletions` are `0`\n> for every file and `isBinary` is `false`. Rules should match on\n> `path` for ADO PRs and avoid line-count thresholds.\n\n### Commits\n\n`commits` is an array of commit objects.\n\n| Property | Type | Description |\n|---|---|---|\n| `message` | string | Commit message |\n| `author` | string | Commit author username |\n| `date` | ISO-8601 string | Commit timestamp |\n\nUse `commits.length` or `commits.count()` to count total commits.\n\n> **Provider note (Azure DevOps):** commit messages are fetched for every\n> PR and exposed via `commits[].message`. Per-commit `author` and\n> `date` are populated from the PR author and `pr.lastUpdated`\n> respectively, since ADO does not return per-commit metadata cheaply.\n\n### Labels\n\n`labels` is an array of strings (the label names applied to the PR).\nUse `\"bug\" in labels` to check membership.\n\n### Reviewers\n\n`reviewers` is an array of strings \u2014 the display name (falling back to\nunique name) of each reviewer. To check whether a particular reviewer is\npresent, use `\"alice\" in reviewers` or `reviewers.any(r -> r == \"alice\")`.\n\n> **Note:** reviewer approval state is not currently exposed in the\n> evaluation context. A rule cannot distinguish approved vs. pending\n> reviewers; it can only count or name-match them.\n\n### Issue link fields\n\n| Variable | Type | Description |\n|---|---|---|\n| `hasLinkedIssue` | boolean | `true` when at least one issue is linked |\n| `linkedIssueKeys` | string[] | Array of linked issue keys (e.g. `[\"PROJ-42\"]`) |\n\n---\n\n## Operators\n\n### Comparison\n\n| Operator | Meaning | Example |\n|---|---|---|\n| `==` | Equal | `pr.isDraft == true` |\n| `!=` | Not equal | `pr.author != \"bot\"` |\n| `>` | Greater than | `files.count() > 20` |\n| `>=` | Greater than or equal | `files.count() >= 10` |\n| `<` | Less than | `commits.count() < 3` |\n| `<=` | Less than or equal | `reviewers.count() <= 1` |\n| `in` | Array or substring membership | `\"bug\" in labels` |\n\n### Logical\n\n| Operator | Precedence (lower = binds tighter) |\n|---|---|\n| `!` (unary not) | 1 |\n| `&&` (and) | 2 |\n| `||` (or) | 3 |\n\nParentheses may be used to override precedence: `(a || b) && c`.\n\n---\n\n## Built-in Functions\n\n### Array methods\n\nCalled on an array variable with dot notation. `any`/`all`/`count(lambda)`\ntake a lambda `x -> expr`.\n\n| Method | Signature | Description |\n|---|---|---|\n| `.any()` | `array.any(x -> expr)` | Returns `true` if **any** element satisfies `expr` |\n| `.all()` | `array.all(x -> expr)` | Returns `true` if **all** elements satisfy `expr` |\n| `.count()` | `array.count()` *or* `array.count(x -> expr)` | Element count; with a predicate, counts matching elements |\n| `.length` | `array.length` | Element count (no parens; identical to `.count()`) |\n\n### String methods\n\n| Method | Signature | Description |\n|---|---|---|\n| `.matches(re)` | `str.matches(string)` | Returns `true` if `str` matches the RE2 regex `re`. **RE2 syntax \u2014 not JS regex.** |\n| `.startsWith(prefix)` | `str.startsWith(string)` | Prefix check |\n| `.endsWith(suffix)` | `str.endsWith(string)` | Suffix check |\n| `.length` | `str.length` | Character length |\n\n> **RE2 note:** RE2 does not support lookaheads (`(?=...)`), lookbehinds\n> (`(?<=...)`), or backreferences (`\\1`). Use character classes and\n> quantifiers instead. String contents are passed to RE2 **verbatim** \u2014\n> write a single backslash where you would write one in a regex literal.\n\n### Free functions\n\n| Function | Signature | Description |\n|---|---|---|\n| `pathMatches(path, pattern)` | `pathMatches(string, string)` | Glob match. `**` = recursive dir wildcard, `*` = single-segment wildcard. |\n| `daysAgo(dateStr)` | `daysAgo(string) -> number` | Whole days between `dateStr` (ISO-8601) and now. Returns `Infinity` if unparseable. |\n\n---\n\n## String Interpolation\n\nReason and flag strings support `${...}` interpolation. Only simple dotted\npaths are allowed inside the braces \u2014 no method calls or arithmetic.\n\n```\nwhen files.count() > 4 then +1 reason \"${files.length} files touched\"\nwhen commits.count() > 10 then -1 reason \"noisy: ${commits.length} commits\"\n```\n\n---\n\n## Runnable Examples\n\n### Example 1 \u2014 Reward test coverage, penalise env-file touches\n\n```\n# +1 if the PR includes any test files\nwhen files.any(f -> pathMatches(f.path, \"**/*.test.ts\")) then +1 reason \"has tests\"\n\n# -5 and flag when .env files are touched (security risk)\nwhen files.any(f -> pathMatches(f.path, \"**/.env*\")) then -5 reason \"touches env\" flag \"env-file\"\n```\n\n### Example 2 \u2014 Multi-condition ruleset\n\n```\n# Draft PRs get a small penalty\nwhen pr.isDraft == true then -1 reason \"draft PR\"\n\n# Large PRs are harder to review\nwhen files.count() > 30 then -2 reason \"large diff \u2014 consider splitting\"\n\n# Bonus for linking an issue\nwhen hasLinkedIssue == true then +1 reason \"linked to tracked issue\"\n\n# At least one reviewer assigned\nwhen reviewers.count() > 0 then +1 reason \"has reviewers\"\n\n# Migration SQL is high-risk\nwhen files.count(f -> pathMatches(f.path, \"**/migrations/**/*.sql\")) > 0 then -3 reason \"migration SQL\" flag \"schema-change\"\n\n# Stale PR \u2014 open longer than a week\nwhen daysAgo(pr.lastUpdated) > 7 then -1 reason \"stale PR\"\n\n# Title check \u2014 must not be a bare word (RE2 syntax)\nwhen pr.title.matches(\"^fix$\") then -1 reason \"title too vague\"\n```\n\n---\n\n## Return Type for Parse Errors\n\nWhen `llama_set_pr_scorer_rules` receives a syntactically invalid ruleset,\nit returns a **structured** parse-error array \u2014 not a flattened string \u2014 so\nClaude can identify and fix individual lines:\n\n```json\n{\n \"success\": false,\n \"parseErrors\": [\n { \"line\": 3, \"column\": 12, \"message\": \"Expected 'then' keyword\" },\n { \"line\": 7, \"column\": 1, \"message\": \"Score +15 exceeds maximum of +10\" }\n ]\n}\n```\n\nFix each error by its `line` + `column` and resubmit.\n";
4
+ export declare const getPrScorerSchemaToolSchema: z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>;
5
+ export type GetPrScorerSchemaToolInput = z.infer<typeof getPrScorerSchemaToolSchema>;
6
+ export declare function executeGetPrScorerSchema(): Promise<string>;
7
+ export declare const getPrScorerRulesToolName = "llama_get_pr_scorer_rules";
8
+ export declare const getPrScorerRulesToolDescription: string;
9
+ export declare const getPrScorerRulesToolSchema: z.ZodObject<{
10
+ orgSlug: z.ZodOptional<z.ZodString>;
11
+ projectKey: z.ZodOptional<z.ZodString>;
12
+ }, "strip", z.ZodTypeAny, {
13
+ orgSlug?: string | undefined;
14
+ projectKey?: string | undefined;
15
+ }, {
16
+ orgSlug?: string | undefined;
17
+ projectKey?: string | undefined;
18
+ }>;
19
+ export type GetPrScorerRulesToolInput = z.infer<typeof getPrScorerRulesToolSchema>;
20
+ export declare function executeGetPrScorerRules(input: GetPrScorerRulesToolInput): Promise<string>;
21
+ export declare const setPrScorerRulesToolName = "llama_set_pr_scorer_rules";
22
+ export declare const setPrScorerRulesToolDescription: string;
23
+ export declare const setPrScorerRulesToolSchema: z.ZodObject<{
24
+ orgSlug: z.ZodOptional<z.ZodString>;
25
+ projectKey: z.ZodOptional<z.ZodString>;
26
+ source: z.ZodString;
27
+ enabled: z.ZodOptional<z.ZodBoolean>;
28
+ }, "strip", z.ZodTypeAny, {
29
+ source: string;
30
+ orgSlug?: string | undefined;
31
+ projectKey?: string | undefined;
32
+ enabled?: boolean | undefined;
33
+ }, {
34
+ source: string;
35
+ orgSlug?: string | undefined;
36
+ projectKey?: string | undefined;
37
+ enabled?: boolean | undefined;
38
+ }>;
39
+ export type SetPrScorerRulesToolInput = z.infer<typeof setPrScorerRulesToolSchema>;
40
+ export declare function executeSetPrScorerRules(input: SetPrScorerRulesToolInput): Promise<string>;
41
+ //# sourceMappingURL=prScorer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prScorer.d.ts","sourceRoot":"","sources":["../../src/tools/prScorer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AASxB,eAAO,MAAM,yBAAyB,+BAA+B,CAAC;AAEtE,eAAO,MAAM,gCAAgC,soRAA0B,CAAC;AAExE,eAAO,MAAM,2BAA2B,gDAAe,CAAC;AAExD,MAAM,MAAM,0BAA0B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2BAA2B,CAAC,CAAC;AAErF,wBAAsB,wBAAwB,IAAI,OAAO,CAAC,MAAM,CAAC,CAEhE;AAMD,eAAO,MAAM,wBAAwB,8BAA8B,CAAC;AAEpE,eAAO,MAAM,+BAA+B,QAGU,CAAC;AAEvD,eAAO,MAAM,0BAA0B;;;;;;;;;EASrC,CAAC;AAEH,MAAM,MAAM,yBAAyB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAcnF,wBAAsB,uBAAuB,CAC3C,KAAK,EAAE,yBAAyB,GAC/B,OAAO,CAAC,MAAM,CAAC,CAsDjB;AAMD,eAAO,MAAM,wBAAwB,8BAA8B,CAAC;AAEpE,eAAO,MAAM,+BAA+B,QAKiD,CAAC;AAE9F,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;EAgBrC,CAAC;AAEH,MAAM,MAAM,yBAAyB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAQnF,wBAAsB,uBAAuB,CAC3C,KAAK,EAAE,yBAAyB,GAC/B,OAAO,CAAC,MAAM,CAAC,CAuFjB"}
@@ -0,0 +1,182 @@
1
+ import { z } from 'zod';
2
+ import { getApiClient, LlamaApiError } from '../api-client.js';
3
+ import { getSessionDefaults } from './session.js';
4
+ import { PR_SCORER_DSL_REFERENCE } from './prScorerSchema.js';
5
+ // ============================================
6
+ // llama_get_pr_scorer_schema
7
+ // ============================================
8
+ export const getPrScorerSchemaToolName = 'llama_get_pr_scorer_schema';
9
+ export const getPrScorerSchemaToolDescription = PR_SCORER_DSL_REFERENCE;
10
+ export const getPrScorerSchemaToolSchema = z.object({});
11
+ export async function executeGetPrScorerSchema() {
12
+ return PR_SCORER_DSL_REFERENCE;
13
+ }
14
+ // ============================================
15
+ // llama_get_pr_scorer_rules
16
+ // ============================================
17
+ export const getPrScorerRulesToolName = 'llama_get_pr_scorer_rules';
18
+ export const getPrScorerRulesToolDescription = 'Get the current PR Scorer ruleset for a project. Returns the DSL source text, ' +
19
+ 'whether scoring is enabled, and metadata. Use llama_get_pr_scorer_schema to understand ' +
20
+ 'the rule language before reading or editing rules.';
21
+ export const getPrScorerRulesToolSchema = z.object({
22
+ orgSlug: z
23
+ .string()
24
+ .optional()
25
+ .describe('Organization slug (session default)'),
26
+ projectKey: z
27
+ .string()
28
+ .optional()
29
+ .describe('Project key (session default)'),
30
+ });
31
+ export async function executeGetPrScorerRules(input) {
32
+ try {
33
+ const session = await getSessionDefaults();
34
+ const orgSlug = input.orgSlug ?? session?.orgSlug;
35
+ const projectKey = input.projectKey ?? session?.projectKey;
36
+ if (!orgSlug) {
37
+ return JSON.stringify({
38
+ success: false,
39
+ error: 'orgSlug is required. Either provide it or set session context with llama_set_context first.',
40
+ });
41
+ }
42
+ if (!projectKey) {
43
+ return JSON.stringify({
44
+ success: false,
45
+ error: 'projectKey is required. Either provide it or set session context with llama_set_context first.',
46
+ });
47
+ }
48
+ const client = getApiClient();
49
+ try {
50
+ await client.recordToolCall('llama_get_pr_scorer_rules', { orgSlug, projectKey });
51
+ }
52
+ catch {
53
+ // Ignore recording errors
54
+ }
55
+ const data = await client.get(`/organizations/${orgSlug}/projects/${projectKey}/pr-scorer/rules`);
56
+ return JSON.stringify({
57
+ success: true,
58
+ orgSlug,
59
+ projectKey,
60
+ source: data.rules?.source ?? '',
61
+ enabled: data.enabled,
62
+ updatedById: data.updatedById ?? null,
63
+ historyLength: data.history?.length ?? 0,
64
+ });
65
+ }
66
+ catch (error) {
67
+ if (error instanceof LlamaApiError) {
68
+ return JSON.stringify({
69
+ success: false,
70
+ error: `Failed to get PR scorer rules: ${error.message}`,
71
+ statusCode: error.statusCode,
72
+ });
73
+ }
74
+ return JSON.stringify({
75
+ success: false,
76
+ error: error instanceof Error ? error.message : 'Unknown error',
77
+ });
78
+ }
79
+ }
80
+ // ============================================
81
+ // llama_set_pr_scorer_rules
82
+ // ============================================
83
+ export const setPrScorerRulesToolName = 'llama_set_pr_scorer_rules';
84
+ export const setPrScorerRulesToolDescription = 'Install or replace the PR Scorer ruleset for a project. Provide DSL source text; ' +
85
+ 'the server validates the syntax before saving. On parse failure the response contains a ' +
86
+ 'structured parseErrors array — NOT a flattened string — so each error can be pinpointed ' +
87
+ 'and fixed by line/column. Call llama_get_pr_scorer_schema to learn the DSL grammar before ' +
88
+ 'authoring rules. Tip: start with the runnable examples in the schema doc, then customise.';
89
+ export const setPrScorerRulesToolSchema = z.object({
90
+ orgSlug: z
91
+ .string()
92
+ .optional()
93
+ .describe('Organization slug (session default)'),
94
+ projectKey: z
95
+ .string()
96
+ .optional()
97
+ .describe('Project key (session default)'),
98
+ source: z
99
+ .string()
100
+ .describe('Full PR Scorer ruleset in DSL source text. Must be valid per the grammar returned by llama_get_pr_scorer_schema.'),
101
+ enabled: z
102
+ .boolean()
103
+ .optional()
104
+ .describe('Whether PR scoring is active for this project. Preserves existing value when not supplied; defaults to false on first save.'),
105
+ });
106
+ export async function executeSetPrScorerRules(input) {
107
+ try {
108
+ const session = await getSessionDefaults();
109
+ const orgSlug = input.orgSlug ?? session?.orgSlug;
110
+ const projectKey = input.projectKey ?? session?.projectKey;
111
+ if (!orgSlug) {
112
+ return JSON.stringify({
113
+ success: false,
114
+ error: 'orgSlug is required. Either provide it or set session context with llama_set_context first.',
115
+ });
116
+ }
117
+ if (!projectKey) {
118
+ return JSON.stringify({
119
+ success: false,
120
+ error: 'projectKey is required. Either provide it or set session context with llama_set_context first.',
121
+ });
122
+ }
123
+ const client = getApiClient();
124
+ try {
125
+ await client.recordToolCall('llama_set_pr_scorer_rules', {
126
+ orgSlug,
127
+ projectKey,
128
+ sourceLength: input.source.length,
129
+ });
130
+ }
131
+ catch {
132
+ // Ignore recording errors
133
+ }
134
+ const data = await client.put(`/organizations/${orgSlug}/projects/${projectKey}/pr-scorer/rules`, {
135
+ source: input.source,
136
+ ...(input.enabled !== undefined ? { enabled: input.enabled } : {}),
137
+ });
138
+ return JSON.stringify({
139
+ success: true,
140
+ orgSlug,
141
+ projectKey,
142
+ source: data.rules?.source ?? '',
143
+ enabled: data.enabled,
144
+ updatedById: data.updatedById ?? null,
145
+ message: 'PR Scorer rules saved successfully.',
146
+ });
147
+ }
148
+ catch (error) {
149
+ // Surface parse errors as a structured array using err.details (set by api-client
150
+ // from the raw response body). No JSON.parse of message strings needed.
151
+ if (error instanceof LlamaApiError && error.statusCode === 400) {
152
+ if (Array.isArray(error.details)) {
153
+ const parseErrors = error.details.map((d) => ({
154
+ line: typeof d.line === 'number' ? d.line : 0,
155
+ column: typeof d.column === 'number' ? d.column : 0,
156
+ message: typeof d.message === 'string' ? d.message : String(d.message ?? ''),
157
+ }));
158
+ return JSON.stringify({
159
+ success: false,
160
+ parseErrors,
161
+ });
162
+ }
163
+ return JSON.stringify({
164
+ success: false,
165
+ error: `Failed to save PR scorer rules: ${error.message}`,
166
+ statusCode: error.statusCode,
167
+ });
168
+ }
169
+ if (error instanceof LlamaApiError) {
170
+ return JSON.stringify({
171
+ success: false,
172
+ error: `Failed to save PR scorer rules: ${error.message}`,
173
+ statusCode: error.statusCode,
174
+ });
175
+ }
176
+ return JSON.stringify({
177
+ success: false,
178
+ error: error instanceof Error ? error.message : 'Unknown error',
179
+ });
180
+ }
181
+ }
182
+ //# sourceMappingURL=prScorer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prScorer.js","sourceRoot":"","sources":["../../src/tools/prScorer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,53 @@
1
+ import { z } from 'zod';
2
+ export declare const testPrScorerToolName = "llama_test_pr_scorer";
3
+ export declare const testPrScorerToolDescription: string;
4
+ export declare const testPrScorerToolSchema: z.ZodObject<{
5
+ orgSlug: z.ZodOptional<z.ZodString>;
6
+ projectKey: z.ZodOptional<z.ZodString>;
7
+ source: z.ZodString;
8
+ prId: z.ZodString;
9
+ }, "strip", z.ZodTypeAny, {
10
+ source: string;
11
+ prId: string;
12
+ orgSlug?: string | undefined;
13
+ projectKey?: string | undefined;
14
+ }, {
15
+ source: string;
16
+ prId: string;
17
+ orgSlug?: string | undefined;
18
+ projectKey?: string | undefined;
19
+ }>;
20
+ export type TestPrScorerToolInput = z.infer<typeof testPrScorerToolSchema>;
21
+ export declare function executeTestPrScorer(input: TestPrScorerToolInput): Promise<string>;
22
+ export declare const listPrScorerHistoryToolName = "llama_list_pr_scorer_history";
23
+ export declare const listPrScorerHistoryToolDescription: string;
24
+ export declare const listPrScorerHistoryToolSchema: z.ZodObject<{
25
+ orgSlug: z.ZodOptional<z.ZodString>;
26
+ projectKey: z.ZodOptional<z.ZodString>;
27
+ }, "strip", z.ZodTypeAny, {
28
+ orgSlug?: string | undefined;
29
+ projectKey?: string | undefined;
30
+ }, {
31
+ orgSlug?: string | undefined;
32
+ projectKey?: string | undefined;
33
+ }>;
34
+ export type ListPrScorerHistoryToolInput = z.infer<typeof listPrScorerHistoryToolSchema>;
35
+ export declare function executeListPrScorerHistory(input: ListPrScorerHistoryToolInput): Promise<string>;
36
+ export declare const revertPrScorerToolName = "llama_revert_pr_scorer";
37
+ export declare const revertPrScorerToolDescription: string;
38
+ export declare const revertPrScorerToolSchema: z.ZodObject<{
39
+ orgSlug: z.ZodOptional<z.ZodString>;
40
+ projectKey: z.ZodOptional<z.ZodString>;
41
+ historyIndex: z.ZodNumber;
42
+ }, "strip", z.ZodTypeAny, {
43
+ historyIndex: number;
44
+ orgSlug?: string | undefined;
45
+ projectKey?: string | undefined;
46
+ }, {
47
+ historyIndex: number;
48
+ orgSlug?: string | undefined;
49
+ projectKey?: string | undefined;
50
+ }>;
51
+ export type RevertPrScorerToolInput = z.infer<typeof revertPrScorerToolSchema>;
52
+ export declare function executeRevertPrScorer(input: RevertPrScorerToolInput): Promise<string>;
53
+ //# sourceMappingURL=prScorerHistory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prScorerHistory.d.ts","sourceRoot":"","sources":["../../src/tools/prScorerHistory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAiCxB,eAAO,MAAM,oBAAoB,yBAAyB,CAAC;AAE3D,eAAO,MAAM,2BAA2B,QAQwF,CAAC;AAEjI,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;EAoBjC,CAAC;AAEH,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAgB3E,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,qBAAqB,GAC3B,OAAO,CAAC,MAAM,CAAC,CAqEjB;AAMD,eAAO,MAAM,2BAA2B,iCAAiC,CAAC;AAE1E,eAAO,MAAM,kCAAkC,QAIwC,CAAC;AAExF,eAAO,MAAM,6BAA6B;;;;;;;;;EASxC,CAAC;AAEH,MAAM,MAAM,4BAA4B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,6BAA6B,CAAC,CAAC;AAUzF,wBAAsB,0BAA0B,CAC9C,KAAK,EAAE,4BAA4B,GAClC,OAAO,CAAC,MAAM,CAAC,CAwDjB;AAMD,eAAO,MAAM,sBAAsB,2BAA2B,CAAC;AAE/D,eAAO,MAAM,6BAA6B,QAIkD,CAAC;AAE7F,eAAO,MAAM,wBAAwB;;;;;;;;;;;;EAgBnC,CAAC;AAEH,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAE/E,wBAAsB,qBAAqB,CACzC,KAAK,EAAE,uBAAuB,GAC7B,OAAO,CAAC,MAAM,CAAC,CAgDjB"}
@@ -0,0 +1,251 @@
1
+ import { z } from 'zod';
2
+ import { getApiClient, LlamaApiError } from '../api-client.js';
3
+ import { getSessionDefaults } from './session.js';
4
+ // ============================================
5
+ // Shared context helper
6
+ // ============================================
7
+ async function resolveContext(orgSlug, projectKey) {
8
+ const session = await getSessionDefaults();
9
+ const resolvedOrg = orgSlug ?? session?.orgSlug;
10
+ const resolvedProject = projectKey ?? session?.projectKey;
11
+ if (!resolvedOrg) {
12
+ return {
13
+ error: 'orgSlug is required. Either provide it or set session context with llama_set_context first.',
14
+ };
15
+ }
16
+ if (!resolvedProject) {
17
+ return {
18
+ error: 'projectKey is required. Either provide it or set session context with llama_set_context first.',
19
+ };
20
+ }
21
+ return { orgSlug: resolvedOrg, projectKey: resolvedProject };
22
+ }
23
+ // ============================================
24
+ // llama_test_pr_scorer
25
+ // ============================================
26
+ export const testPrScorerToolName = 'llama_test_pr_scorer';
27
+ export const testPrScorerToolDescription = 'Dry-run a PR Scorer ruleset against a real PR without saving the rules. ' +
28
+ 'Returns the full evaluation result including score, grade, reasons, flags, and a per-rule trace. ' +
29
+ 'Use this to validate new or edited rules before calling llama_set_pr_scorer_rules.\n\n' +
30
+ 'prId format: "<adoRepoId>:<prNumber>" (e.g. "abc123-def-456:42"). ' +
31
+ 'These composite IDs are returned by the GET /pr-scorer/recent-prs endpoint that the editor dry-run pane uses; ' +
32
+ 'they are NOT the DevLink UUID and NOT the bare ADO PR number.\n\n' +
33
+ 'trace[] contains one entry per rule: { ruleIndex, matched, delta, reason?, flag? }. ' +
34
+ 'Use trace to explain why a specific rule fired or did not fire (e.g. delta=0 + matched=false means the condition was false).';
35
+ export const testPrScorerToolSchema = z.object({
36
+ orgSlug: z
37
+ .string()
38
+ .optional()
39
+ .describe('Organization slug (session default)'),
40
+ projectKey: z
41
+ .string()
42
+ .optional()
43
+ .describe('Project key (session default)'),
44
+ source: z
45
+ .string()
46
+ .describe('DSL rules to test. May differ from the currently saved ruleset — this is a dry run.'),
47
+ prId: z
48
+ .string()
49
+ .describe('Composite ADO PR id in the format "<adoRepoId>:<prNumber>" (e.g. "abc123-def-456:42"). ' +
50
+ 'Obtain from GET /pr-scorer/recent-prs. NOT the DevLink UUID.'),
51
+ });
52
+ export async function executeTestPrScorer(input) {
53
+ try {
54
+ const ctx = await resolveContext(input.orgSlug, input.projectKey);
55
+ if ('error' in ctx) {
56
+ return JSON.stringify({ success: false, error: ctx.error });
57
+ }
58
+ const client = getApiClient();
59
+ try {
60
+ await client.recordToolCall('llama_test_pr_scorer', {
61
+ orgSlug: ctx.orgSlug,
62
+ projectKey: ctx.projectKey,
63
+ prId: input.prId,
64
+ sourceLength: input.source.length,
65
+ });
66
+ }
67
+ catch {
68
+ // Ignore recording errors
69
+ }
70
+ const data = await client.postPrScorerTest(ctx.orgSlug, ctx.projectKey, input.source, input.prId);
71
+ return JSON.stringify({
72
+ success: true,
73
+ orgSlug: ctx.orgSlug,
74
+ projectKey: ctx.projectKey,
75
+ prId: input.prId,
76
+ score: data.score,
77
+ grade: data.grade,
78
+ reasons: data.reasons ?? [],
79
+ flags: data.flags ?? [],
80
+ trace: (data.trace ?? []),
81
+ });
82
+ }
83
+ catch (error) {
84
+ // Surface parse errors the same way as llama_set_pr_scorer_rules
85
+ if (error instanceof LlamaApiError && error.statusCode === 400) {
86
+ if (Array.isArray(error.details)) {
87
+ const parseErrors = error.details.map((d) => ({
88
+ line: typeof d.line === 'number' ? d.line : 0,
89
+ column: typeof d.column === 'number' ? d.column : 0,
90
+ message: typeof d.message === 'string' ? d.message : String(d.message ?? ''),
91
+ }));
92
+ return JSON.stringify({ success: false, parseErrors });
93
+ }
94
+ return JSON.stringify({
95
+ success: false,
96
+ error: `PR scorer test failed: ${error.message}`,
97
+ statusCode: error.statusCode,
98
+ });
99
+ }
100
+ if (error instanceof LlamaApiError) {
101
+ return JSON.stringify({
102
+ success: false,
103
+ error: `PR scorer test failed: ${error.message}`,
104
+ statusCode: error.statusCode,
105
+ });
106
+ }
107
+ return JSON.stringify({
108
+ success: false,
109
+ error: error instanceof Error ? error.message : 'Unknown error',
110
+ });
111
+ }
112
+ }
113
+ // ============================================
114
+ // llama_list_pr_scorer_history
115
+ // ============================================
116
+ export const listPrScorerHistoryToolName = 'llama_list_pr_scorer_history';
117
+ export const listPrScorerHistoryToolDescription = 'List the save history for a project\'s PR Scorer ruleset. ' +
118
+ 'Returns metadata only (timestamps + updatedById); full rule bodies are stripped to keep token cost low. ' +
119
+ 'Entries are ordered most-recent-first; the index of each entry corresponds to the historyIndex ' +
120
+ 'accepted by llama_revert_pr_scorer (0 = most recent save before the current state).';
121
+ export const listPrScorerHistoryToolSchema = z.object({
122
+ orgSlug: z
123
+ .string()
124
+ .optional()
125
+ .describe('Organization slug (session default)'),
126
+ projectKey: z
127
+ .string()
128
+ .optional()
129
+ .describe('Project key (session default)'),
130
+ });
131
+ export async function executeListPrScorerHistory(input) {
132
+ try {
133
+ const ctx = await resolveContext(input.orgSlug, input.projectKey);
134
+ if ('error' in ctx) {
135
+ return JSON.stringify({ success: false, error: ctx.error });
136
+ }
137
+ const client = getApiClient();
138
+ try {
139
+ await client.recordToolCall('llama_list_pr_scorer_history', {
140
+ orgSlug: ctx.orgSlug,
141
+ projectKey: ctx.projectKey,
142
+ });
143
+ }
144
+ catch {
145
+ // Ignore recording errors
146
+ }
147
+ const raw = await client.getPrScorerHistory(ctx.orgSlug, ctx.projectKey);
148
+ // Strip source + ast fields — return metadata only per spec
149
+ const entries = (raw ?? []).map((entry, index) => {
150
+ const meta = {
151
+ index,
152
+ savedAt: entry.savedAt,
153
+ };
154
+ if (entry.updatedById !== undefined) {
155
+ meta.updatedById = entry.updatedById;
156
+ }
157
+ if (typeof entry.source === 'string') {
158
+ meta.sourceLineCount = entry.source.split('\n').length;
159
+ meta.sourceLength = entry.source.length;
160
+ }
161
+ return meta;
162
+ });
163
+ return JSON.stringify({
164
+ success: true,
165
+ orgSlug: ctx.orgSlug,
166
+ projectKey: ctx.projectKey,
167
+ count: entries.length,
168
+ entries,
169
+ });
170
+ }
171
+ catch (error) {
172
+ if (error instanceof LlamaApiError) {
173
+ return JSON.stringify({
174
+ success: false,
175
+ error: `Failed to list PR scorer history: ${error.message}`,
176
+ statusCode: error.statusCode,
177
+ });
178
+ }
179
+ return JSON.stringify({
180
+ success: false,
181
+ error: error instanceof Error ? error.message : 'Unknown error',
182
+ });
183
+ }
184
+ }
185
+ // ============================================
186
+ // llama_revert_pr_scorer
187
+ // ============================================
188
+ export const revertPrScorerToolName = 'llama_revert_pr_scorer';
189
+ export const revertPrScorerToolDescription = 'Revert the PR Scorer ruleset to a previous saved version. ' +
190
+ 'historyIndex is 0-indexed from most-recent-first (i.e. 0 = the most recent save before the current state). ' +
191
+ 'Call llama_list_pr_scorer_history first to see available indices and their timestamps. ' +
192
+ 'After a successful revert, call llama_get_pr_scorer_rules to confirm the active ruleset.';
193
+ export const revertPrScorerToolSchema = z.object({
194
+ orgSlug: z
195
+ .string()
196
+ .optional()
197
+ .describe('Organization slug (session default)'),
198
+ projectKey: z
199
+ .string()
200
+ .optional()
201
+ .describe('Project key (session default)'),
202
+ historyIndex: z
203
+ .number()
204
+ .int()
205
+ .min(0)
206
+ .describe('0-indexed position from most-recent-first history. Use llama_list_pr_scorer_history to find available indices.'),
207
+ });
208
+ export async function executeRevertPrScorer(input) {
209
+ try {
210
+ const ctx = await resolveContext(input.orgSlug, input.projectKey);
211
+ if ('error' in ctx) {
212
+ return JSON.stringify({ success: false, error: ctx.error });
213
+ }
214
+ const client = getApiClient();
215
+ try {
216
+ await client.recordToolCall('llama_revert_pr_scorer', {
217
+ orgSlug: ctx.orgSlug,
218
+ projectKey: ctx.projectKey,
219
+ historyIndex: input.historyIndex,
220
+ });
221
+ }
222
+ catch {
223
+ // Ignore recording errors
224
+ }
225
+ const data = await client.postPrScorerRevert(ctx.orgSlug, ctx.projectKey, input.historyIndex);
226
+ return JSON.stringify({
227
+ success: true,
228
+ orgSlug: ctx.orgSlug,
229
+ projectKey: ctx.projectKey,
230
+ historyIndex: input.historyIndex,
231
+ source: data?.rules?.source ?? '',
232
+ enabled: data?.enabled ?? true,
233
+ updatedById: data?.updatedById ?? null,
234
+ message: `PR Scorer ruleset reverted to history index ${input.historyIndex}.`,
235
+ });
236
+ }
237
+ catch (error) {
238
+ if (error instanceof LlamaApiError) {
239
+ return JSON.stringify({
240
+ success: false,
241
+ error: `Failed to revert PR scorer: ${error.message}`,
242
+ statusCode: error.statusCode,
243
+ });
244
+ }
245
+ return JSON.stringify({
246
+ success: false,
247
+ error: error instanceof Error ? error.message : 'Unknown error',
248
+ });
249
+ }
250
+ }
251
+ //# sourceMappingURL=prScorerHistory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prScorerHistory.js","sourceRoot":"","sources":["../../src/tools/prScorerHistory.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Full DSL reference for the PR Scorer rule language.
3
+ * Exported as a string so it can be embedded in the llama_get_pr_scorer_schema
4
+ * tool description AND returned as the handler response.
5
+ *
6
+ * Spec: LLAMA-1283
7
+ *
8
+ * IMPORTANT: This file is the canonical, machine-readable DSL reference. It
9
+ * MUST match the runtime exposed by packages/pr-scorer-dsl (parser allowed
10
+ * methods, evaluator lookupName(), and the EvalContext shape assembled in
11
+ * apps/api/src/services/prScorerDispatcher.service.ts). When you change the
12
+ * DSL, update this file AND apps/web/src/pages/docs/PrScorerDocsPage.tsx.
13
+ */
14
+ export declare const PR_SCORER_DSL_REFERENCE = "# PR Scorer Rule Language \u2014 Full DSL Reference\n\nPR Scorer rules let you automatically adjust the quality score of a pull\nrequest based on its content, metadata, and linked issues. Each rule is a\nsingle line that conditionally adds or subtracts points and optionally\nattaches a human-readable reason and flag label.\n\n---\n\n## Grammar (EBNF)\n\n```\nruleset := rule*\nrule := 'when' expr 'then' SignedInt ( 'reason' STRING )? ( 'flag' STRING )?\nSignedInt := ( '+' | '-' ) INTEGER // range: [-10, +10] inclusive\nSTRING := '\"' [^\"]* '\"'\n```\n\nBlank lines and lines beginning with `#` are treated as comments and are\nsilently ignored. Rules are evaluated in order; all matching rules fire\n(scores accumulate \u2014 there is no early-exit).\n\n### Hard limits\n\n| Constraint | Value |\n|---|---|\n| Maximum rules per ruleset | 100 |\n| Maximum nested any() / all() / count(lambda) depth | 8 |\n| Score per rule action | [-10, +10] |\n\n---\n\n## Evaluation Context \u2014 Variables\n\nEvery rule's `expr` can reference the following variables. All property\naccesses are null-safe: accessing a missing property returns `null` (which\nis falsy).\n\n### Top-level PR fields\n\n| Variable | Type | Description |\n|---|---|---|\n| `pr.id` | number | Pull request id (provider-native, e.g. ADO `pullRequestId`) |\n| `pr.title` | string | Pull request title |\n| `pr.description` | string | PR body / description |\n| `pr.author` | string | Display name (or unique name) of the PR author |\n| `pr.lastUpdated` | ISO-8601 string | Timestamp of last update |\n| `pr.isDraft` | boolean | `true` when the PR is in draft state |\n| `pr.filesChanged` | number | Total count of changed files in the PR |\n| `pr.commitCount` | number | Total count of commits in the PR |\n| `pr.linesAdded` | number \\| null | Aggregate lines added across the PR (null if the provider didn't return it) |\n| `pr.linesRemoved` | number \\| null | Aggregate lines removed across the PR (null if the provider didn't return it) |\n\n> The aggregate fields above are the cheapest signals for \"this PR is large.\"\n> Per-file line counts are not available from ADO, so prefer\n> `pr.filesChanged > 50` or `pr.linesAdded > 1000` over file-level thresholds.\n\n### Files\n\n`files` is an array of file-change objects.\n\n| Property | Type | Description |\n|---|---|---|\n| `path` | string | File path relative to repo root |\n| `additions` | number | Lines added in this file |\n| `deletions` | number | Lines deleted in this file |\n| `isBinary` | boolean | `true` if the file is binary |\n\nUse `files.length` or `files.count()` to count total changed files.\n\n> **Provider caveat (Azure DevOps):** the ADO `/stats` endpoint does not\n> return per-file line counts, so `additions` and `deletions` are `0`\n> for every file and `isBinary` is `false`. Rules should match on\n> `path` for ADO PRs and avoid line-count thresholds.\n\n### Commits\n\n`commits` is an array of commit objects.\n\n| Property | Type | Description |\n|---|---|---|\n| `message` | string | Commit message |\n| `author` | string | Commit author username |\n| `date` | ISO-8601 string | Commit timestamp |\n\nUse `commits.length` or `commits.count()` to count total commits.\n\n> **Provider note (Azure DevOps):** commit messages are fetched for every\n> PR and exposed via `commits[].message`. Per-commit `author` and\n> `date` are populated from the PR author and `pr.lastUpdated`\n> respectively, since ADO does not return per-commit metadata cheaply.\n\n### Labels\n\n`labels` is an array of strings (the label names applied to the PR).\nUse `\"bug\" in labels` to check membership.\n\n### Reviewers\n\n`reviewers` is an array of strings \u2014 the display name (falling back to\nunique name) of each reviewer. To check whether a particular reviewer is\npresent, use `\"alice\" in reviewers` or `reviewers.any(r -> r == \"alice\")`.\n\n> **Note:** reviewer approval state is not currently exposed in the\n> evaluation context. A rule cannot distinguish approved vs. pending\n> reviewers; it can only count or name-match them.\n\n### Issue link fields\n\n| Variable | Type | Description |\n|---|---|---|\n| `hasLinkedIssue` | boolean | `true` when at least one issue is linked |\n| `linkedIssueKeys` | string[] | Array of linked issue keys (e.g. `[\"PROJ-42\"]`) |\n\n---\n\n## Operators\n\n### Comparison\n\n| Operator | Meaning | Example |\n|---|---|---|\n| `==` | Equal | `pr.isDraft == true` |\n| `!=` | Not equal | `pr.author != \"bot\"` |\n| `>` | Greater than | `files.count() > 20` |\n| `>=` | Greater than or equal | `files.count() >= 10` |\n| `<` | Less than | `commits.count() < 3` |\n| `<=` | Less than or equal | `reviewers.count() <= 1` |\n| `in` | Array or substring membership | `\"bug\" in labels` |\n\n### Logical\n\n| Operator | Precedence (lower = binds tighter) |\n|---|---|\n| `!` (unary not) | 1 |\n| `&&` (and) | 2 |\n| `||` (or) | 3 |\n\nParentheses may be used to override precedence: `(a || b) && c`.\n\n---\n\n## Built-in Functions\n\n### Array methods\n\nCalled on an array variable with dot notation. `any`/`all`/`count(lambda)`\ntake a lambda `x -> expr`.\n\n| Method | Signature | Description |\n|---|---|---|\n| `.any()` | `array.any(x -> expr)` | Returns `true` if **any** element satisfies `expr` |\n| `.all()` | `array.all(x -> expr)` | Returns `true` if **all** elements satisfy `expr` |\n| `.count()` | `array.count()` *or* `array.count(x -> expr)` | Element count; with a predicate, counts matching elements |\n| `.length` | `array.length` | Element count (no parens; identical to `.count()`) |\n\n### String methods\n\n| Method | Signature | Description |\n|---|---|---|\n| `.matches(re)` | `str.matches(string)` | Returns `true` if `str` matches the RE2 regex `re`. **RE2 syntax \u2014 not JS regex.** |\n| `.startsWith(prefix)` | `str.startsWith(string)` | Prefix check |\n| `.endsWith(suffix)` | `str.endsWith(string)` | Suffix check |\n| `.length` | `str.length` | Character length |\n\n> **RE2 note:** RE2 does not support lookaheads (`(?=...)`), lookbehinds\n> (`(?<=...)`), or backreferences (`\\1`). Use character classes and\n> quantifiers instead. String contents are passed to RE2 **verbatim** \u2014\n> write a single backslash where you would write one in a regex literal.\n\n### Free functions\n\n| Function | Signature | Description |\n|---|---|---|\n| `pathMatches(path, pattern)` | `pathMatches(string, string)` | Glob match. `**` = recursive dir wildcard, `*` = single-segment wildcard. |\n| `daysAgo(dateStr)` | `daysAgo(string) -> number` | Whole days between `dateStr` (ISO-8601) and now. Returns `Infinity` if unparseable. |\n\n---\n\n## String Interpolation\n\nReason and flag strings support `${...}` interpolation. Only simple dotted\npaths are allowed inside the braces \u2014 no method calls or arithmetic.\n\n```\nwhen files.count() > 4 then +1 reason \"${files.length} files touched\"\nwhen commits.count() > 10 then -1 reason \"noisy: ${commits.length} commits\"\n```\n\n---\n\n## Runnable Examples\n\n### Example 1 \u2014 Reward test coverage, penalise env-file touches\n\n```\n# +1 if the PR includes any test files\nwhen files.any(f -> pathMatches(f.path, \"**/*.test.ts\")) then +1 reason \"has tests\"\n\n# -5 and flag when .env files are touched (security risk)\nwhen files.any(f -> pathMatches(f.path, \"**/.env*\")) then -5 reason \"touches env\" flag \"env-file\"\n```\n\n### Example 2 \u2014 Multi-condition ruleset\n\n```\n# Draft PRs get a small penalty\nwhen pr.isDraft == true then -1 reason \"draft PR\"\n\n# Large PRs are harder to review\nwhen files.count() > 30 then -2 reason \"large diff \u2014 consider splitting\"\n\n# Bonus for linking an issue\nwhen hasLinkedIssue == true then +1 reason \"linked to tracked issue\"\n\n# At least one reviewer assigned\nwhen reviewers.count() > 0 then +1 reason \"has reviewers\"\n\n# Migration SQL is high-risk\nwhen files.count(f -> pathMatches(f.path, \"**/migrations/**/*.sql\")) > 0 then -3 reason \"migration SQL\" flag \"schema-change\"\n\n# Stale PR \u2014 open longer than a week\nwhen daysAgo(pr.lastUpdated) > 7 then -1 reason \"stale PR\"\n\n# Title check \u2014 must not be a bare word (RE2 syntax)\nwhen pr.title.matches(\"^fix$\") then -1 reason \"title too vague\"\n```\n\n---\n\n## Return Type for Parse Errors\n\nWhen `llama_set_pr_scorer_rules` receives a syntactically invalid ruleset,\nit returns a **structured** parse-error array \u2014 not a flattened string \u2014 so\nClaude can identify and fix individual lines:\n\n```json\n{\n \"success\": false,\n \"parseErrors\": [\n { \"line\": 3, \"column\": 12, \"message\": \"Expected 'then' keyword\" },\n { \"line\": 7, \"column\": 1, \"message\": \"Score +15 exceeds maximum of +10\" }\n ]\n}\n```\n\nFix each error by its `line` + `column` and resubmit.\n";
15
+ //# sourceMappingURL=prScorerSchema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prScorerSchema.d.ts","sourceRoot":"","sources":["../../src/tools/prScorerSchema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,eAAO,MAAM,uBAAuB,soRAuPnC,CAAC"}