codeloop-mcp-server 0.1.14 → 0.1.16

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 (84) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +75 -0
  3. package/dist/auth/local_mode.d.ts +32 -0
  4. package/dist/auth/local_mode.d.ts.map +1 -0
  5. package/dist/auth/local_mode.js +56 -0
  6. package/dist/auth/local_mode.js.map +1 -0
  7. package/dist/auth/usage_tracker.d.ts +11 -1
  8. package/dist/auth/usage_tracker.d.ts.map +1 -1
  9. package/dist/auth/usage_tracker.js +51 -4
  10. package/dist/auth/usage_tracker.js.map +1 -1
  11. package/dist/environment/presets.d.ts +46 -0
  12. package/dist/environment/presets.d.ts.map +1 -0
  13. package/dist/environment/presets.js +109 -0
  14. package/dist/environment/presets.js.map +1 -0
  15. package/dist/evidence/baseline_governance.d.ts +62 -0
  16. package/dist/evidence/baseline_governance.d.ts.map +1 -0
  17. package/dist/evidence/baseline_governance.js +113 -0
  18. package/dist/evidence/baseline_governance.js.map +1 -0
  19. package/dist/evidence/run_lineage.d.ts +66 -0
  20. package/dist/evidence/run_lineage.d.ts.map +1 -0
  21. package/dist/evidence/run_lineage.js +138 -0
  22. package/dist/evidence/run_lineage.js.map +1 -0
  23. package/dist/evidence/screenshot_diff.d.ts +6 -2
  24. package/dist/evidence/screenshot_diff.d.ts.map +1 -1
  25. package/dist/evidence/screenshot_diff.js +40 -3
  26. package/dist/evidence/screenshot_diff.js.map +1 -1
  27. package/dist/evidence/visual_attribution.d.ts +32 -0
  28. package/dist/evidence/visual_attribution.d.ts.map +1 -0
  29. package/dist/evidence/visual_attribution.js +88 -0
  30. package/dist/evidence/visual_attribution.js.map +1 -0
  31. package/dist/index.js +163 -1
  32. package/dist/index.js.map +1 -1
  33. package/dist/prompt_manager/index.d.ts +27 -0
  34. package/dist/prompt_manager/index.d.ts.map +1 -0
  35. package/dist/prompt_manager/index.js +28 -0
  36. package/dist/prompt_manager/index.js.map +1 -0
  37. package/dist/prompt_manager/state_machine.d.ts +55 -0
  38. package/dist/prompt_manager/state_machine.d.ts.map +1 -0
  39. package/dist/prompt_manager/state_machine.js +60 -0
  40. package/dist/prompt_manager/state_machine.js.map +1 -0
  41. package/dist/prompt_manager/templates.d.ts +43 -0
  42. package/dist/prompt_manager/templates.d.ts.map +1 -0
  43. package/dist/prompt_manager/templates.js +177 -0
  44. package/dist/prompt_manager/templates.js.map +1 -0
  45. package/dist/runners/base.d.ts +1 -1
  46. package/dist/runners/base.d.ts.map +1 -1
  47. package/dist/runners/base.js +2 -2
  48. package/dist/runners/base.js.map +1 -1
  49. package/dist/runners/figma_spec_generator.d.ts +54 -0
  50. package/dist/runners/figma_spec_generator.d.ts.map +1 -0
  51. package/dist/runners/figma_spec_generator.js +227 -0
  52. package/dist/runners/figma_spec_generator.js.map +1 -0
  53. package/dist/runners/generic.js +23 -20
  54. package/dist/runners/generic.js.map +1 -1
  55. package/dist/runners/playwright.d.ts +9 -1
  56. package/dist/runners/playwright.d.ts.map +1 -1
  57. package/dist/runners/playwright.js +18 -3
  58. package/dist/runners/playwright.js.map +1 -1
  59. package/dist/runners/plugin_sdk.d.ts +25 -0
  60. package/dist/runners/plugin_sdk.d.ts.map +1 -0
  61. package/dist/runners/plugin_sdk.js +86 -0
  62. package/dist/runners/plugin_sdk.js.map +1 -0
  63. package/dist/state/dependency_graph.d.ts +23 -0
  64. package/dist/state/dependency_graph.d.ts.map +1 -0
  65. package/dist/state/dependency_graph.js +127 -0
  66. package/dist/state/dependency_graph.js.map +1 -0
  67. package/dist/state/section_registry.d.ts.map +1 -1
  68. package/dist/state/section_registry.js +11 -5
  69. package/dist/state/section_registry.js.map +1 -1
  70. package/dist/tools/design_compare.js +2 -2
  71. package/dist/tools/design_compare.js.map +1 -1
  72. package/dist/tools/init-project.d.ts.map +1 -1
  73. package/dist/tools/init-project.js +40 -262
  74. package/dist/tools/init-project.js.map +1 -1
  75. package/dist/tools/update_baseline.d.ts +3 -0
  76. package/dist/tools/update_baseline.d.ts.map +1 -1
  77. package/dist/tools/update_baseline.js +18 -2
  78. package/dist/tools/update_baseline.js.map +1 -1
  79. package/dist/tools/verify.d.ts.map +1 -1
  80. package/dist/tools/verify.js +66 -4
  81. package/dist/tools/verify.js.map +1 -1
  82. package/dist/tools/visual_review.js +1 -1
  83. package/dist/tools/visual_review.js.map +1 -1
  84. package/package.json +28 -4
@@ -0,0 +1,227 @@
1
+ /**
2
+ * Figma Spec Generator — pulls design tokens (colors, typography, spacing)
3
+ * from a Figma file's styles and writes them to `docs/specs/` and
4
+ * `docs/ui_rules.md`. Extends the existing Figma fetcher with token-level
5
+ * extraction via the Figma REST API v1 `files/:key` endpoint.
6
+ */
7
+ import { mkdirSync, writeFileSync } from "fs";
8
+ import { join } from "path";
9
+ import { loadFigmaConfig, resolveFigmaToken, parseFigmaFileKey, } from "./figma_fetcher.js";
10
+ function rgbaToHex(r, g, b) {
11
+ const toHex = (v) => Math.round(v * 255)
12
+ .toString(16)
13
+ .padStart(2, "0");
14
+ return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
15
+ }
16
+ /**
17
+ * Extract design tokens from a Figma file using the REST API.
18
+ */
19
+ export async function extractTokensFromFigma(fileKey, token) {
20
+ const errors = [];
21
+ const colors = [];
22
+ const typography = [];
23
+ const spacing = [];
24
+ let fileData;
25
+ try {
26
+ const resp = await fetch(`https://api.figma.com/v1/files/${fileKey}/styles`, {
27
+ headers: { "X-Figma-Token": token },
28
+ });
29
+ if (!resp.ok) {
30
+ errors.push(`Figma styles API returned ${resp.status}`);
31
+ return {
32
+ tokens: { colors, typography, spacing, extracted_at: new Date().toISOString(), figma_file_key: fileKey },
33
+ errors,
34
+ };
35
+ }
36
+ fileData = (await resp.json());
37
+ }
38
+ catch (err) {
39
+ errors.push(`Network error: ${err.message}`);
40
+ return {
41
+ tokens: { colors, typography, spacing, extracted_at: new Date().toISOString(), figma_file_key: fileKey },
42
+ errors,
43
+ };
44
+ }
45
+ const meta = fileData.meta;
46
+ const styles = meta?.styles ?? [];
47
+ const colorStyleKeys = [];
48
+ const textStyleKeys = [];
49
+ for (const style of styles) {
50
+ if (style.style_type === "FILL") {
51
+ colorStyleKeys.push(style.key);
52
+ colors.push({
53
+ name: style.name,
54
+ hex: "#000000",
55
+ opacity: 1,
56
+ r: 0,
57
+ g: 0,
58
+ b: 0,
59
+ });
60
+ }
61
+ else if (style.style_type === "TEXT") {
62
+ textStyleKeys.push(style.key);
63
+ typography.push({
64
+ name: style.name,
65
+ family: "Unknown",
66
+ weight: 400,
67
+ size: 16,
68
+ });
69
+ }
70
+ }
71
+ try {
72
+ // depth=4 keeps the document payload bounded while still surfacing
73
+ // tokens that live inside frames/components/component-sets a few levels
74
+ // deep. We then traverse the returned subtree recursively up to a hard
75
+ // depth cap to avoid runaway traversal on huge files.
76
+ const fileResp = await fetch(`https://api.figma.com/v1/files/${fileKey}?depth=4`, {
77
+ headers: { "X-Figma-Token": token },
78
+ });
79
+ if (fileResp.ok) {
80
+ const file = (await fileResp.json());
81
+ const doc = file.document;
82
+ if (doc?.children) {
83
+ extractTokensFromNodes(doc.children, colors, typography, spacing);
84
+ }
85
+ }
86
+ }
87
+ catch { /* swallow — we already have style names */ }
88
+ return {
89
+ tokens: {
90
+ colors,
91
+ typography,
92
+ spacing,
93
+ extracted_at: new Date().toISOString(),
94
+ figma_file_key: fileKey,
95
+ },
96
+ errors,
97
+ };
98
+ }
99
+ /**
100
+ * Hard cap on tree traversal. depth=4 fetches roughly the visual hierarchy
101
+ * we care about (page → frame → component → variant → leaf), and the cap
102
+ * here protects us if Figma ever returns deeper inline trees (e.g. nested
103
+ * component sets). Anything deeper than 8 is almost always implementation
104
+ * detail unrelated to design tokens.
105
+ */
106
+ const MAX_TRAVERSAL_DEPTH = 8;
107
+ function extractTokensFromNodes(nodes, colors, typography, spacing, depth = 0) {
108
+ if (depth > MAX_TRAVERSAL_DEPTH)
109
+ return;
110
+ for (const node of nodes) {
111
+ if (node.fills && Array.isArray(node.fills)) {
112
+ for (const fill of node.fills) {
113
+ if (fill.type === "SOLID" && fill.color) {
114
+ const existing = colors.find((c) => c.name === node.name);
115
+ if (existing) {
116
+ existing.r = fill.color.r;
117
+ existing.g = fill.color.g;
118
+ existing.b = fill.color.b;
119
+ existing.opacity = fill.color.a ?? 1;
120
+ existing.hex = rgbaToHex(fill.color.r, fill.color.g, fill.color.b);
121
+ }
122
+ }
123
+ }
124
+ }
125
+ if (node.style && typeof node.style === "object") {
126
+ const s = node.style;
127
+ if (s.fontFamily) {
128
+ const existing = typography.find((t) => t.name === node.name);
129
+ if (existing) {
130
+ existing.family = String(s.fontFamily);
131
+ existing.weight = Number(s.fontWeight) || 400;
132
+ existing.size = Number(s.fontSize) || 16;
133
+ if (s.lineHeightPx)
134
+ existing.line_height = Number(s.lineHeightPx);
135
+ if (s.letterSpacing)
136
+ existing.letter_spacing = Number(s.letterSpacing);
137
+ }
138
+ }
139
+ }
140
+ if (node.itemSpacing && node.name) {
141
+ spacing.push({ name: `${node.name}/gap`, value: node.itemSpacing });
142
+ }
143
+ if (node.paddingLeft && node.name) {
144
+ spacing.push({ name: `${node.name}/padding`, value: node.paddingLeft });
145
+ }
146
+ if (node.children) {
147
+ extractTokensFromNodes(node.children, colors, typography, spacing, depth + 1);
148
+ }
149
+ }
150
+ }
151
+ export function writeTokenFiles(cwd, tokens) {
152
+ const specsDir = join(cwd, "docs", "specs");
153
+ mkdirSync(specsDir, { recursive: true });
154
+ const specPath = join(specsDir, "design_tokens.json");
155
+ writeFileSync(specPath, JSON.stringify(tokens, null, 2));
156
+ const rulesPath = join(cwd, "docs", "ui_rules.md");
157
+ const md = generateUiRulesMarkdown(tokens);
158
+ writeFileSync(rulesPath, md);
159
+ return { specPath, rulesPath };
160
+ }
161
+ function generateUiRulesMarkdown(tokens) {
162
+ const lines = [
163
+ "# UI Design Rules",
164
+ "",
165
+ `> Auto-generated from Figma (file: \`${tokens.figma_file_key}\`) on ${tokens.extracted_at}`,
166
+ "",
167
+ ];
168
+ if (tokens.colors.length > 0) {
169
+ lines.push("## Colors", "");
170
+ lines.push("| Name | Hex | Opacity |");
171
+ lines.push("|------|-----|---------|");
172
+ for (const c of tokens.colors) {
173
+ lines.push(`| ${c.name} | \`${c.hex}\` | ${c.opacity} |`);
174
+ }
175
+ lines.push("");
176
+ }
177
+ if (tokens.typography.length > 0) {
178
+ lines.push("## Typography", "");
179
+ lines.push("| Name | Family | Weight | Size | Line Height |");
180
+ lines.push("|------|--------|--------|------|-------------|");
181
+ for (const t of tokens.typography) {
182
+ lines.push(`| ${t.name} | ${t.family} | ${t.weight} | ${t.size}px | ${t.line_height ? `${t.line_height}px` : "auto"} |`);
183
+ }
184
+ lines.push("");
185
+ }
186
+ if (tokens.spacing.length > 0) {
187
+ lines.push("## Spacing", "");
188
+ lines.push("| Name | Value |");
189
+ lines.push("|------|-------|");
190
+ for (const s of tokens.spacing) {
191
+ lines.push(`| ${s.name} | ${s.value}px |`);
192
+ }
193
+ lines.push("");
194
+ }
195
+ lines.push("---", "", "These rules are enforced by CodeLoop's `codeloop_design_compare` tool during verification.");
196
+ return lines.join("\n");
197
+ }
198
+ /**
199
+ * Full pipeline: load Figma config -> extract tokens -> write docs.
200
+ */
201
+ export async function generateSpec(cwd) {
202
+ const config = loadFigmaConfig(cwd);
203
+ if (!config) {
204
+ return {
205
+ tokens: { colors: [], typography: [], spacing: [], extracted_at: new Date().toISOString(), figma_file_key: "" },
206
+ errors: ["No .codeloop/figma.json found."],
207
+ };
208
+ }
209
+ const token = resolveFigmaToken(config);
210
+ if (!token) {
211
+ return {
212
+ tokens: { colors: [], typography: [], spacing: [], extracted_at: new Date().toISOString(), figma_file_key: "" },
213
+ errors: ["No Figma API token configured."],
214
+ };
215
+ }
216
+ const fileKey = config.file_key || (config.file_url ? parseFigmaFileKey(config.file_url) : null);
217
+ if (!fileKey) {
218
+ return {
219
+ tokens: { colors: [], typography: [], spacing: [], extracted_at: new Date().toISOString(), figma_file_key: "" },
220
+ errors: ["No Figma file key found."],
221
+ };
222
+ }
223
+ const { tokens, errors } = await extractTokensFromFigma(fileKey, token);
224
+ const { specPath, rulesPath } = writeTokenFiles(cwd, tokens);
225
+ return { tokens, errors, specPath, rulesPath };
226
+ }
227
+ //# sourceMappingURL=figma_spec_generator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"figma_spec_generator.js","sourceRoot":"","sources":["../../src/runners/figma_spec_generator.ts"],"names":[],"mappings":"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"}
@@ -38,28 +38,31 @@ function stripAnsi(str) {
38
38
  // eslint-disable-next-line no-control-regex
39
39
  return str.replace(/\x1B\[[0-9;]*[A-Za-z]/g, "");
40
40
  }
41
+ function sumMatches(output, pattern) {
42
+ let total = 0;
43
+ for (const match of output.matchAll(pattern)) {
44
+ total += parseInt(match[1], 10);
45
+ }
46
+ return total;
47
+ }
41
48
  function parseTestOutput(output) {
42
- let passed = 0;
43
- let failed = 0;
44
- let skipped = 0;
45
49
  const clean = stripAnsi(output);
46
- // Vitest/Jest format: "Tests 12 passed (12)" — strip ANSI first
47
- const vitestMatch = clean.match(/Tests\s+(\d+)\s+passed/);
48
- if (vitestMatch)
49
- passed = parseInt(vitestMatch[1], 10);
50
- const vitestFail = clean.match(/Tests\s+(\d+)\s+failed/);
51
- if (vitestFail)
52
- failed = parseInt(vitestFail[1], 10);
53
- // Mocha/tap format: "X passing" / "X failing"
54
- const mochaPass = clean.match(/(\d+)\s+passing/);
55
- if (mochaPass && !vitestMatch)
56
- passed = parseInt(mochaPass[1], 10);
57
- const mochaFail = clean.match(/(\d+)\s+failing/);
58
- if (mochaFail && !vitestFail)
59
- failed = parseInt(mochaFail[1], 10);
60
- const skipMatch = clean.match(/(\d+)\s+(?:skipped|pending)/);
61
- if (skipMatch)
62
- skipped = parseInt(skipMatch[1], 10);
50
+ // Vitest/Jest format: "Tests 12 passed (12)" — sum across all packages so
51
+ // monorepo runs (turbo, nx, lerna) report the full coverage instead of just
52
+ // the first runner that flushed to stdout. The narrow "Tests N passed"
53
+ // anchor avoids accidentally matching a script's preview text.
54
+ const vitestPassed = sumMatches(clean, /Tests\s+(\d+)\s+passed/g);
55
+ const vitestFailed = sumMatches(clean, /Tests\s+(\d+)\s+failed/g);
56
+ // Mocha/tap format: "X passing" / "X failing". We deliberately match only
57
+ // the first occurrence to avoid double-counting npm's command-echo line.
58
+ const mochaPassMatch = clean.match(/(\d+)\s+passing/);
59
+ const mochaFailMatch = clean.match(/(\d+)\s+failing/);
60
+ const mochaPassed = mochaPassMatch ? parseInt(mochaPassMatch[1], 10) : 0;
61
+ const mochaFailed = mochaFailMatch ? parseInt(mochaFailMatch[1], 10) : 0;
62
+ const passed = vitestPassed > 0 ? vitestPassed : mochaPassed;
63
+ const failed = vitestFailed > 0 ? vitestFailed : mochaFailed;
64
+ const skippedMatch = clean.match(/(\d+)\s+(?:skipped|pending)/);
65
+ const skipped = skippedMatch ? parseInt(skippedMatch[1], 10) : 0;
63
66
  if (passed === 0 && failed === 0) {
64
67
  return { passed: 0, failed: 0, skipped: 0 };
65
68
  }
@@ -1 +1 @@
1
- {"version":3,"file":"generic.js","sourceRoot":"","sources":["../../src/runners/generic.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"generic.js","sourceRoot":"","sources":["../../src/runners/generic.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,11 @@
1
1
  import type { RunnerResult } from "./base.js";
2
- export declare function runPlaywrightTests(cwd: string, logPath: string, jsonReportPath?: string): Promise<RunnerResult>;
2
+ export interface PlaywrightEnvOverrides {
3
+ viewportWidth?: number;
4
+ viewportHeight?: number;
5
+ deviceScaleFactor?: number;
6
+ isMobile?: boolean;
7
+ locale?: string;
8
+ timezone?: string;
9
+ }
10
+ export declare function runPlaywrightTests(cwd: string, logPath: string, jsonReportPath?: string, envOverrides?: PlaywrightEnvOverrides): Promise<RunnerResult>;
3
11
  //# sourceMappingURL=playwright.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"playwright.d.ts","sourceRoot":"","sources":["../../src/runners/playwright.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAI9C,wBAAsB,kBAAkB,CACtC,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,EACf,cAAc,CAAC,EAAE,MAAM,GACtB,OAAO,CAAC,YAAY,CAAC,CAuCvB"}
1
+ {"version":3,"file":"playwright.d.ts","sourceRoot":"","sources":["../../src/runners/playwright.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAI9C,MAAM,WAAW,sBAAsB;IACrC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,wBAAsB,kBAAkB,CACtC,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,EACf,cAAc,CAAC,EAAE,MAAM,EACvB,YAAY,CAAC,EAAE,sBAAsB,GACpC,OAAO,CAAC,YAAY,CAAC,CAmDvB"}
@@ -1,8 +1,7 @@
1
1
  import { runCommand, checkToolAvailable, makeSkippedResult } from "./base.js";
2
2
  import { existsSync, readFileSync } from "fs";
3
3
  import { join } from "path";
4
- export async function runPlaywrightTests(cwd, logPath, jsonReportPath) {
5
- // Check for playwright config
4
+ export async function runPlaywrightTests(cwd, logPath, jsonReportPath, envOverrides) {
6
5
  const hasConfig = existsSync(join(cwd, "playwright.config.ts")) ||
7
6
  existsSync(join(cwd, "playwright.config.js"));
8
7
  if (!hasConfig) {
@@ -12,7 +11,23 @@ export async function runPlaywrightTests(cwd, logPath, jsonReportPath) {
12
11
  return makeSkippedResult("playwright", "npx not found on PATH");
13
12
  }
14
13
  const reportPath = jsonReportPath || join(cwd, "playwright-report.json");
15
- const result = await runCommand("npx", ["playwright", "test", "--reporter=json"], cwd, logPath);
14
+ // CodeLoop normalisation env vars; users can read these in their
15
+ // playwright.config.ts via `process.env.CODELOOP_VIEWPORT_WIDTH` etc.
16
+ // to lock viewport, locale, timezone for reproducibility.
17
+ const extraEnv = {};
18
+ if (envOverrides?.viewportWidth)
19
+ extraEnv.CODELOOP_VIEWPORT_WIDTH = String(envOverrides.viewportWidth);
20
+ if (envOverrides?.viewportHeight)
21
+ extraEnv.CODELOOP_VIEWPORT_HEIGHT = String(envOverrides.viewportHeight);
22
+ if (envOverrides?.deviceScaleFactor)
23
+ extraEnv.CODELOOP_DEVICE_SCALE_FACTOR = String(envOverrides.deviceScaleFactor);
24
+ if (envOverrides?.isMobile !== undefined)
25
+ extraEnv.CODELOOP_IS_MOBILE = envOverrides.isMobile ? "1" : "0";
26
+ if (envOverrides?.locale)
27
+ extraEnv.CODELOOP_LOCALE = envOverrides.locale;
28
+ if (envOverrides?.timezone)
29
+ extraEnv.CODELOOP_TIMEZONE = envOverrides.timezone;
30
+ const result = await runCommand("npx", ["playwright", "test", "--reporter=json"], cwd, logPath, Object.keys(extraEnv).length > 0 ? extraEnv : undefined);
16
31
  const { passed, failed, skipped } = parsePlaywrightOutput(result.stdout, reportPath);
17
32
  return {
18
33
  runner_name: "playwright",
@@ -1 +1 @@
1
- {"version":3,"file":"playwright.js","sourceRoot":"","sources":["../../src/runners/playwright.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAE9E,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAC9C,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,GAAW,EACX,OAAe,EACf,cAAuB;IAEvB,8BAA8B;IAC9B,MAAM,SAAS,GACb,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,sBAAsB,CAAC,CAAC;QAC7C,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,sBAAsB,CAAC,CAAC,CAAC;IAEhD,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO,iBAAiB,CAAC,YAAY,EAAE,4BAA4B,CAAC,CAAC;IACvE,CAAC;IAED,IAAI,CAAC,CAAC,MAAM,kBAAkB,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;QACvC,OAAO,iBAAiB,CAAC,YAAY,EAAE,uBAAuB,CAAC,CAAC;IAClE,CAAC;IAED,MAAM,UAAU,GAAG,cAAc,IAAI,IAAI,CAAC,GAAG,EAAE,wBAAwB,CAAC,CAAC;IACzE,MAAM,MAAM,GAAG,MAAM,UAAU,CAC7B,KAAK,EACL,CAAC,YAAY,EAAE,MAAM,EAAE,iBAAiB,CAAC,EACzC,GAAG,EACH,OAAO,CACR,CAAC;IAEF,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,qBAAqB,CACvD,MAAM,CAAC,MAAM,EACb,UAAU,CACX,CAAC;IAEF,OAAO;QACL,WAAW,EAAE,YAAY;QACzB,SAAS,EAAE,IAAI;QACf,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,MAAM;QACN,MAAM;QACN,OAAO;QACP,QAAQ,EAAE,OAAO;QACjB,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,MAAM,EAAE,MAAM,CAAC,MAAM;KACtB,CAAC;AACJ,CAAC;AAED,SAAS,qBAAqB,CAC5B,MAAc,EACd,UAAkB;IAElB,wBAAwB;IACxB,IAAI,CAAC;QACH,IAAI,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAC3B,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC;YAC7D,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;gBACjB,OAAO;oBACL,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,QAAQ,IAAI,CAAC;oBAClC,MAAM,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC,CAAC;oBAClE,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,OAAO,IAAI,CAAC;iBACnC,CAAC;YACJ,CAAC;QACH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,iCAAiC;IACnC,CAAC;IAED,uEAAuE;IACvE,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QACtC,IAAI,UAAU,CAAC,KAAK,EAAE,CAAC;YACrB,OAAO;gBACL,MAAM,EAAE,UAAU,CAAC,KAAK,CAAC,QAAQ,IAAI,CAAC;gBACtC,MAAM,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,UAAU,IAAI,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC,CAAC;gBAC1E,OAAO,EAAE,UAAU,CAAC,KAAK,CAAC,OAAO,IAAI,CAAC;aACvC,CAAC;QACJ,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,gCAAgC;IAClC,CAAC;IAED,sDAAsD;IACtD,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,IAAI,OAAO,GAAG,CAAC,CAAC;IAEhB,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;IACjD,IAAI,SAAS;QAAE,MAAM,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAEnD,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;IACjD,IAAI,SAAS;QAAE,MAAM,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAEnD,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;IAClD,IAAI,SAAS;QAAE,OAAO,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAEpD,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;AACrC,CAAC"}
1
+ {"version":3,"file":"playwright.js","sourceRoot":"","sources":["../../src/runners/playwright.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Plugin SDK — defines the runner plugin interface and provides a registry
3
+ * for custom runners. Third-party frameworks (Django, Rails, etc.) implement
4
+ * the `CodeLoopRunner` interface and register via `.codeloop/plugins.json`.
5
+ */
6
+ import type { RunnerResult } from "./base.js";
7
+ export interface CodeLoopRunner {
8
+ name: string;
9
+ detect: (cwd: string) => boolean;
10
+ run: (cwd: string, logPath: string) => Promise<RunnerResult>;
11
+ }
12
+ export interface PluginConfig {
13
+ name: string;
14
+ command: string;
15
+ args?: string[];
16
+ detect_file?: string;
17
+ parse_output?: "jest" | "pytest" | "rspec" | "generic" | "exit_code";
18
+ }
19
+ export interface PluginsManifest {
20
+ plugins: PluginConfig[];
21
+ }
22
+ export declare function loadPluginsManifest(cwd: string): PluginsManifest;
23
+ export declare function createRunnerFromPlugin(plugin: PluginConfig): CodeLoopRunner;
24
+ export declare function loadCustomRunners(cwd: string): CodeLoopRunner[];
25
+ //# sourceMappingURL=plugin_sdk.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin_sdk.d.ts","sourceRoot":"","sources":["../../src/runners/plugin_sdk.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAG9C,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;IACjC,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;CAC9D;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,GAAG,SAAS,GAAG,WAAW,CAAC;CACtE;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,YAAY,EAAE,CAAC;CACzB;AAID,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,CAShE;AA0BD,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,YAAY,GAAG,cAAc,CAmC3E;AAED,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc,EAAE,CAK/D"}
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Plugin SDK — defines the runner plugin interface and provides a registry
3
+ * for custom runners. Third-party frameworks (Django, Rails, etc.) implement
4
+ * the `CodeLoopRunner` interface and register via `.codeloop/plugins.json`.
5
+ */
6
+ import { existsSync, readFileSync } from "fs";
7
+ import { join } from "path";
8
+ import { runCommand } from "./base.js";
9
+ const PLUGINS_FILE = ".codeloop/plugins.json";
10
+ export function loadPluginsManifest(cwd) {
11
+ const p = join(cwd, PLUGINS_FILE);
12
+ if (!existsSync(p))
13
+ return { plugins: [] };
14
+ try {
15
+ const raw = JSON.parse(readFileSync(p, "utf-8"));
16
+ return Array.isArray(raw.plugins) ? raw : { plugins: [] };
17
+ }
18
+ catch {
19
+ return { plugins: [] };
20
+ }
21
+ }
22
+ function parseGenericOutput(stdout) {
23
+ let passed = 0;
24
+ let failed = 0;
25
+ const skipped = 0;
26
+ const jestMatch = stdout.match(/Tests:\s*(\d+)\s*passed/);
27
+ if (jestMatch)
28
+ passed = parseInt(jestMatch[1]);
29
+ const jestFail = stdout.match(/Tests:\s*(\d+)\s*failed/);
30
+ if (jestFail)
31
+ failed = parseInt(jestFail[1]);
32
+ const pytestMatch = stdout.match(/(\d+)\s*passed/);
33
+ if (pytestMatch)
34
+ passed = parseInt(pytestMatch[1]);
35
+ const pytestFail = stdout.match(/(\d+)\s*failed/);
36
+ if (pytestFail)
37
+ failed = parseInt(pytestFail[1]);
38
+ const rspecMatch = stdout.match(/(\d+)\s*examples?,\s*(\d+)\s*failures?/);
39
+ if (rspecMatch) {
40
+ passed = parseInt(rspecMatch[1]) - parseInt(rspecMatch[2]);
41
+ failed = parseInt(rspecMatch[2]);
42
+ }
43
+ return { passed, failed, skipped };
44
+ }
45
+ export function createRunnerFromPlugin(plugin) {
46
+ return {
47
+ name: plugin.name,
48
+ detect: (cwd) => {
49
+ if (!plugin.detect_file)
50
+ return true;
51
+ return existsSync(join(cwd, plugin.detect_file));
52
+ },
53
+ run: async (cwd, logPath) => {
54
+ const start = Date.now();
55
+ const args = plugin.args ?? [];
56
+ const result = await runCommand(plugin.command, args, cwd, logPath);
57
+ const parseMode = plugin.parse_output ?? "generic";
58
+ let parsed = { passed: 0, failed: 0, skipped: 0 };
59
+ if (parseMode === "exit_code") {
60
+ parsed = { passed: result.exit_code === 0 ? 1 : 0, failed: result.exit_code === 0 ? 0 : 1, skipped: 0 };
61
+ }
62
+ else {
63
+ parsed = parseGenericOutput(result.stdout + "\n" + result.stderr);
64
+ }
65
+ return {
66
+ runner_name: plugin.name,
67
+ available: true,
68
+ exit_code: result.exit_code,
69
+ passed: parsed.passed,
70
+ failed: parsed.failed,
71
+ skipped: parsed.skipped,
72
+ log_path: logPath,
73
+ duration_ms: result.duration_ms,
74
+ stdout: result.stdout,
75
+ stderr: result.stderr,
76
+ };
77
+ },
78
+ };
79
+ }
80
+ export function loadCustomRunners(cwd) {
81
+ const manifest = loadPluginsManifest(cwd);
82
+ return manifest.plugins
83
+ .map(createRunnerFromPlugin)
84
+ .filter((runner) => runner.detect(cwd));
85
+ }
86
+ //# sourceMappingURL=plugin_sdk.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin_sdk.js","sourceRoot":"","sources":["../../src/runners/plugin_sdk.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import type { SectionStateRecord } from "@codelooptech/shared";
2
+ export interface DependencyGraphNode {
3
+ id: string;
4
+ dependsOn: string[];
5
+ dependedOnBy: string[];
6
+ }
7
+ export interface DependencyGraph {
8
+ nodes: Map<string, DependencyGraphNode>;
9
+ /** Topological order of section ids — predecessors first. Empty if the graph contains a cycle. */
10
+ topoOrder: string[];
11
+ /** True iff a cycle was detected during sort. */
12
+ hasCycle: boolean;
13
+ /** When `hasCycle` is true, this contains the ids of one cycle for diagnostics. */
14
+ cycle: string[];
15
+ /** Section ids referenced as dependencies but not present in the input set. */
16
+ unknownDependencies: string[];
17
+ }
18
+ export declare function buildDependencyGraph(sections: readonly SectionStateRecord[]): DependencyGraph;
19
+ /**
20
+ * Returns the maximum dependency depth (longest path) for diagnostics in the dashboard.
21
+ */
22
+ export declare function longestPathLength(graph: DependencyGraph): number;
23
+ //# sourceMappingURL=dependency_graph.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dependency_graph.d.ts","sourceRoot":"","sources":["../../src/state/dependency_graph.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAE/D,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;IACxC,kGAAkG;IAClG,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,iDAAiD;IACjD,QAAQ,EAAE,OAAO,CAAC;IAClB,mFAAmF;IACnF,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,+EAA+E;IAC/E,mBAAmB,EAAE,MAAM,EAAE,CAAC;CAC/B;AAED,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,SAAS,kBAAkB,EAAE,GAAG,eAAe,CA2B7F;AA+ED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,eAAe,GAAG,MAAM,CAqBhE"}