ridgeline 0.7.21 → 0.8.2

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 (169) hide show
  1. package/dist/agents/core/builder.md +15 -0
  2. package/dist/catalog/build-catalog.js +2 -1
  3. package/dist/catalog/build-catalog.js.map +1 -1
  4. package/dist/catalog/classify.js +2 -1
  5. package/dist/catalog/classify.js.map +1 -1
  6. package/dist/catalog/pack-sprites.js +3 -2
  7. package/dist/catalog/pack-sprites.js.map +1 -1
  8. package/dist/catalog/vision-describe.js +3 -2
  9. package/dist/catalog/vision-describe.js.map +1 -1
  10. package/dist/cli.js +112 -44
  11. package/dist/cli.js.map +1 -1
  12. package/dist/commands/build.js +0 -1
  13. package/dist/commands/build.js.map +1 -1
  14. package/dist/commands/check.d.ts +1 -5
  15. package/dist/commands/check.js +2 -60
  16. package/dist/commands/check.js.map +1 -1
  17. package/dist/commands/create.d.ts +0 -1
  18. package/dist/commands/create.js +0 -18
  19. package/dist/commands/create.js.map +1 -1
  20. package/dist/commands/design.d.ts +0 -1
  21. package/dist/commands/design.js +1 -2
  22. package/dist/commands/design.js.map +1 -1
  23. package/dist/commands/qa-workflow.js +6 -5
  24. package/dist/commands/qa-workflow.js.map +1 -1
  25. package/dist/commands/refine.d.ts +0 -1
  26. package/dist/commands/refine.js +0 -1
  27. package/dist/commands/refine.js.map +1 -1
  28. package/dist/commands/research.d.ts +2 -1
  29. package/dist/commands/research.js +2 -2
  30. package/dist/commands/research.js.map +1 -1
  31. package/dist/commands/retrospective.d.ts +0 -1
  32. package/dist/commands/retrospective.js +1 -2
  33. package/dist/commands/retrospective.js.map +1 -1
  34. package/dist/commands/shape.d.ts +30 -1
  35. package/dist/commands/shape.js +16 -5
  36. package/dist/commands/shape.js.map +1 -1
  37. package/dist/commands/spec.d.ts +2 -1
  38. package/dist/commands/spec.js +2 -1
  39. package/dist/commands/spec.js.map +1 -1
  40. package/dist/commands/ui.d.ts +7 -0
  41. package/dist/commands/ui.js +96 -0
  42. package/dist/commands/ui.js.map +1 -0
  43. package/dist/config.js +2 -2
  44. package/dist/config.js.map +1 -1
  45. package/dist/engine/claude/claude.exec.d.ts +11 -0
  46. package/dist/engine/claude/claude.exec.js +73 -36
  47. package/dist/engine/claude/claude.exec.js.map +1 -1
  48. package/dist/engine/claude/stable.prompt.d.ts +31 -0
  49. package/dist/engine/claude/stable.prompt.js +137 -0
  50. package/dist/engine/claude/stable.prompt.js.map +1 -0
  51. package/dist/engine/claude/stream.display.d.ts +1 -1
  52. package/dist/engine/claude/stream.display.js +2 -1
  53. package/dist/engine/claude/stream.display.js.map +1 -1
  54. package/dist/engine/detect/index.d.ts +15 -0
  55. package/dist/engine/detect/index.js +160 -0
  56. package/dist/engine/detect/index.js.map +1 -0
  57. package/dist/engine/discovery/agent.registry.d.ts +5 -6
  58. package/dist/engine/discovery/agent.registry.js +20 -54
  59. package/dist/engine/discovery/agent.registry.js.map +1 -1
  60. package/dist/engine/discovery/skill.check.d.ts +3 -3
  61. package/dist/engine/discovery/skill.check.js +4 -4
  62. package/dist/engine/discovery/skill.check.js.map +1 -1
  63. package/dist/engine/index.d.ts +0 -1
  64. package/dist/engine/index.js +1 -3
  65. package/dist/engine/index.js.map +1 -1
  66. package/dist/engine/pipeline/build.exec.js +19 -6
  67. package/dist/engine/pipeline/build.exec.js.map +1 -1
  68. package/dist/engine/pipeline/ensemble.exec.d.ts +41 -3
  69. package/dist/engine/pipeline/ensemble.exec.js +295 -94
  70. package/dist/engine/pipeline/ensemble.exec.js.map +1 -1
  71. package/dist/engine/pipeline/phase.sequence.js +97 -4
  72. package/dist/engine/pipeline/phase.sequence.js.map +1 -1
  73. package/dist/engine/pipeline/pipeline.shared.d.ts +7 -0
  74. package/dist/engine/pipeline/pipeline.shared.js +21 -3
  75. package/dist/engine/pipeline/pipeline.shared.js.map +1 -1
  76. package/dist/engine/pipeline/refine.exec.d.ts +0 -1
  77. package/dist/engine/pipeline/refine.exec.js +1 -2
  78. package/dist/engine/pipeline/refine.exec.js.map +1 -1
  79. package/dist/engine/pipeline/research.exec.d.ts +2 -1
  80. package/dist/engine/pipeline/research.exec.js +53 -7
  81. package/dist/engine/pipeline/research.exec.js.map +1 -1
  82. package/dist/engine/pipeline/review.exec.d.ts +2 -1
  83. package/dist/engine/pipeline/review.exec.js +14 -6
  84. package/dist/engine/pipeline/review.exec.js.map +1 -1
  85. package/dist/engine/pipeline/sensors.collect.d.ts +6 -0
  86. package/dist/engine/pipeline/sensors.collect.js +34 -0
  87. package/dist/engine/pipeline/sensors.collect.js.map +1 -0
  88. package/dist/engine/pipeline/specialist.verdict.d.ts +19 -0
  89. package/dist/engine/pipeline/specialist.verdict.js +189 -0
  90. package/dist/engine/pipeline/specialist.verdict.js.map +1 -0
  91. package/dist/engine/pipeline/specify.exec.d.ts +2 -1
  92. package/dist/engine/pipeline/specify.exec.js +159 -7
  93. package/dist/engine/pipeline/specify.exec.js.map +1 -1
  94. package/dist/sensors/a11y.d.ts +36 -0
  95. package/dist/sensors/a11y.js +134 -0
  96. package/dist/sensors/a11y.js.map +1 -0
  97. package/dist/sensors/contrast.d.ts +3 -0
  98. package/dist/sensors/contrast.js +117 -0
  99. package/dist/sensors/contrast.js.map +1 -0
  100. package/dist/sensors/index.d.ts +27 -0
  101. package/dist/sensors/index.js +3 -0
  102. package/dist/sensors/index.js.map +1 -0
  103. package/dist/sensors/playwright.d.ts +69 -0
  104. package/dist/sensors/playwright.js +266 -0
  105. package/dist/sensors/playwright.js.map +1 -0
  106. package/dist/sensors/vision.d.ts +18 -0
  107. package/dist/sensors/vision.js +125 -0
  108. package/dist/sensors/vision.js.map +1 -0
  109. package/dist/stores/feedback.format.js +9 -0
  110. package/dist/stores/feedback.format.js.map +1 -1
  111. package/dist/stores/feedback.parse.js +2 -0
  112. package/dist/stores/feedback.parse.js.map +1 -1
  113. package/dist/stores/settings.d.ts +7 -1
  114. package/dist/stores/settings.js +10 -1
  115. package/dist/stores/settings.js.map +1 -1
  116. package/dist/stores/trajectory.d.ts +9 -2
  117. package/dist/stores/trajectory.js +6 -0
  118. package/dist/stores/trajectory.js.map +1 -1
  119. package/dist/types.d.ts +36 -3
  120. package/dist/ui/color.d.ts +16 -0
  121. package/dist/ui/color.js +46 -0
  122. package/dist/ui/color.js.map +1 -0
  123. package/dist/ui/contrast.d.ts +2 -0
  124. package/dist/ui/contrast.js +94 -0
  125. package/dist/ui/contrast.js.map +1 -0
  126. package/dist/ui/dashboard/client.d.ts +1 -0
  127. package/dist/ui/dashboard/client.js +281 -0
  128. package/dist/ui/dashboard/client.js.map +1 -0
  129. package/dist/ui/dashboard/css.d.ts +1 -0
  130. package/dist/ui/dashboard/css.js +341 -0
  131. package/dist/ui/dashboard/css.js.map +1 -0
  132. package/dist/ui/dashboard/events.d.ts +15 -0
  133. package/dist/ui/dashboard/events.js +40 -0
  134. package/dist/ui/dashboard/events.js.map +1 -0
  135. package/dist/ui/dashboard/favicon.d.ts +2 -0
  136. package/dist/ui/dashboard/favicon.js +20 -0
  137. package/dist/ui/dashboard/favicon.js.map +1 -0
  138. package/dist/ui/dashboard/hex.d.ts +7 -0
  139. package/dist/ui/dashboard/hex.js +16 -0
  140. package/dist/ui/dashboard/hex.js.map +1 -0
  141. package/dist/ui/dashboard/html.d.ts +7 -0
  142. package/dist/ui/dashboard/html.js +69 -0
  143. package/dist/ui/dashboard/html.js.map +1 -0
  144. package/dist/ui/dashboard/server.d.ts +26 -0
  145. package/dist/ui/dashboard/server.js +257 -0
  146. package/dist/ui/dashboard/server.js.map +1 -0
  147. package/dist/ui/dashboard/snapshot.d.ts +29 -0
  148. package/dist/ui/dashboard/snapshot.js +71 -0
  149. package/dist/ui/dashboard/snapshot.js.map +1 -0
  150. package/dist/ui/dashboard/tokens.d.ts +19 -0
  151. package/dist/ui/dashboard/tokens.js +25 -0
  152. package/dist/ui/dashboard/tokens.js.map +1 -0
  153. package/dist/ui/dashboard/watcher.d.ts +13 -0
  154. package/dist/ui/dashboard/watcher.js +238 -0
  155. package/dist/ui/dashboard/watcher.js.map +1 -0
  156. package/dist/ui/output.js +3 -2
  157. package/dist/ui/output.js.map +1 -1
  158. package/dist/ui/preflight.d.ts +21 -0
  159. package/dist/ui/preflight.js +159 -0
  160. package/dist/ui/preflight.js.map +1 -0
  161. package/dist/ui/spinner.d.ts +0 -6
  162. package/dist/ui/spinner.js +25 -6
  163. package/dist/ui/spinner.js.map +1 -1
  164. package/dist/ui/transcript.js +2 -3
  165. package/dist/ui/transcript.js.map +1 -1
  166. package/dist/utils/flavour-removed.d.ts +12 -0
  167. package/dist/utils/flavour-removed.js +44 -0
  168. package/dist/utils/flavour-removed.js.map +1 -0
  169. package/package.json +16 -3
@@ -0,0 +1,134 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runA11ySensor = void 0;
4
+ const playwright_1 = require("./playwright");
5
+ const PLAYWRIGHT_INSTALL_HINT = "npm install --save-dev playwright && npx playwright install chromium";
6
+ const isPlaywrightResolvable = () => {
7
+ try {
8
+ require.resolve("playwright");
9
+ return true;
10
+ }
11
+ catch {
12
+ return false;
13
+ }
14
+ };
15
+ const LAUNCH_TIMEOUT_MS = 10_000;
16
+ const defaultA11yLoadPlaywright = () => require("playwright");
17
+ const defaultResolveAxePath = () => require.resolve("axe-core");
18
+ const unresolvableFinding = () => ({
19
+ kind: "a11y",
20
+ severity: "warning",
21
+ summary: `Playwright is not installed. Install with: ${PLAYWRIGHT_INSTALL_HINT}`,
22
+ });
23
+ const isSandboxDetected = (env = process.env) => Boolean(env.RIDGELINE_SANDBOX || env.GREYWALL_ACTIVE || env.BWRAP_DETECTED || env.container);
24
+ const severityFromImpact = (impact) => {
25
+ switch (impact) {
26
+ case "critical":
27
+ case "serious":
28
+ return "error";
29
+ case "moderate":
30
+ return "warning";
31
+ default:
32
+ return "info";
33
+ }
34
+ };
35
+ const formatViolation = (v) => ({
36
+ kind: "a11y",
37
+ severity: severityFromImpact(v.impact ?? null),
38
+ summary: `${v.id} (${v.impact ?? "minor"}): ${v.help ?? v.description} [${v.nodes.length} node${v.nodes.length === 1 ? "" : "s"}]`,
39
+ });
40
+ const runA11ySensor = async (input, internals = {}) => {
41
+ const resolvable = (internals.isResolvable ?? isPlaywrightResolvable)();
42
+ if (!resolvable) {
43
+ return [unresolvableFinding()];
44
+ }
45
+ const port = await (0, playwright_1.resolveDevServerPort)(input).catch(() => null);
46
+ const url = input.url ?? (port && port.source !== "none" ? `http://127.0.0.1:${port.port}` : null);
47
+ if (!url) {
48
+ return [
49
+ {
50
+ kind: "a11y",
51
+ severity: "warning",
52
+ summary: "no dev server URL available for accessibility audit",
53
+ },
54
+ ];
55
+ }
56
+ const load = internals.loadPlaywright ?? defaultA11yLoadPlaywright;
57
+ const sandboxed = (internals.isSandboxed ?? isSandboxDetected)();
58
+ const axePath = (internals.resolveAxePath ?? defaultResolveAxePath)();
59
+ const launchArgs = sandboxed ? ["--no-sandbox", "--disable-setuid-sandbox"] : [];
60
+ let playwright;
61
+ try {
62
+ playwright = load();
63
+ }
64
+ catch (err) {
65
+ const message = err instanceof Error ? err.message : String(err);
66
+ if (message.toLowerCase().includes("cannot find module")) {
67
+ return [unresolvableFinding()];
68
+ }
69
+ return [
70
+ {
71
+ kind: "a11y",
72
+ severity: "warning",
73
+ summary: `accessibility audit skipped — sandbox-incompatible (${message})`,
74
+ },
75
+ ];
76
+ }
77
+ let browser;
78
+ try {
79
+ browser = await playwright.chromium.launch({
80
+ args: launchArgs,
81
+ timeout: LAUNCH_TIMEOUT_MS,
82
+ headless: true,
83
+ });
84
+ }
85
+ catch (err) {
86
+ const message = err instanceof Error ? err.message : String(err);
87
+ if (/executable doesn.?t exist|browser not found|playwright install/i.test(message)) {
88
+ return [unresolvableFinding()];
89
+ }
90
+ return [
91
+ {
92
+ kind: "a11y",
93
+ severity: "warning",
94
+ summary: `accessibility audit skipped — sandbox-incompatible (${message})`,
95
+ },
96
+ ];
97
+ }
98
+ try {
99
+ const page = await browser.newPage();
100
+ await page.goto(url, { waitUntil: "load", timeout: LAUNCH_TIMEOUT_MS });
101
+ await page.addScriptTag({ path: axePath });
102
+ const axeResults = await page.evaluate("window.axe.run(document, { resultTypes: ['violations'] })");
103
+ await page.close();
104
+ await browser.close();
105
+ if (axeResults.violations.length === 0) {
106
+ return [
107
+ {
108
+ kind: "a11y",
109
+ severity: "info",
110
+ summary: `no WCAG AA violations detected at ${url}`,
111
+ },
112
+ ];
113
+ }
114
+ return axeResults.violations.map(formatViolation);
115
+ }
116
+ catch (err) {
117
+ await browser.close().catch(() => { });
118
+ const message = err instanceof Error ? err.message : String(err);
119
+ return [
120
+ {
121
+ kind: "a11y",
122
+ severity: "warning",
123
+ summary: `accessibility audit failed at ${url}: ${message}`,
124
+ },
125
+ ];
126
+ }
127
+ };
128
+ exports.runA11ySensor = runA11ySensor;
129
+ const a11ySensor = {
130
+ name: "a11y",
131
+ run: (input) => (0, exports.runA11ySensor)(input),
132
+ };
133
+ exports.default = a11ySensor;
134
+ //# sourceMappingURL=a11y.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"a11y.js","sourceRoot":"","sources":["../../src/sensors/a11y.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { SensorAdapter } from "./index";
2
+ declare const contrastSensor: SensorAdapter;
3
+ export default contrastSensor;
@@ -0,0 +1,117 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ const fs = __importStar(require("node:fs"));
37
+ const path = __importStar(require("node:path"));
38
+ const wcag_contrast_1 = require("wcag-contrast");
39
+ const WCAG_AA_NORMAL = 4.5;
40
+ const HEX_TOKEN = /#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})\b/g;
41
+ const HEX_VALIDATE = /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/;
42
+ const normalizeHex = (value) => {
43
+ const trimmed = value.trim();
44
+ if (!trimmed.startsWith("#"))
45
+ return `#${trimmed}`;
46
+ return trimmed;
47
+ };
48
+ const isValidHex = (value) => HEX_VALIDATE.test(value);
49
+ const extractPairsFromMarkdown = (content) => {
50
+ const pairs = [];
51
+ const lines = content.split(/\r?\n/);
52
+ for (const line of lines) {
53
+ const tokens = line.match(HEX_TOKEN);
54
+ if (!tokens || tokens.length < 2)
55
+ continue;
56
+ const [bg, fg] = tokens;
57
+ pairs.push({ background: bg, foreground: fg });
58
+ }
59
+ return pairs;
60
+ };
61
+ const discoverPairs = (input) => {
62
+ if (input.contrastPairs && input.contrastPairs.length > 0) {
63
+ return [...input.contrastPairs];
64
+ }
65
+ const ridgelineDir = input.ridgelineDir ?? path.join(input.cwd, ".ridgeline");
66
+ const designPath = path.join(ridgelineDir, "design.md");
67
+ if (!fs.existsSync(designPath))
68
+ return [];
69
+ const content = fs.readFileSync(designPath, "utf-8");
70
+ return extractPairsFromMarkdown(content);
71
+ };
72
+ const scorePair = (pair) => {
73
+ const background = normalizeHex(pair.background);
74
+ const foreground = normalizeHex(pair.foreground);
75
+ if (!isValidHex(background) || !isValidHex(foreground)) {
76
+ return {
77
+ kind: "contrast",
78
+ summary: `invalid hex pair ${foreground} / ${background}`,
79
+ severity: "warning",
80
+ };
81
+ }
82
+ let ratio;
83
+ try {
84
+ ratio = (0, wcag_contrast_1.hex)(foreground, background);
85
+ }
86
+ catch {
87
+ return {
88
+ kind: "contrast",
89
+ summary: `invalid hex pair ${foreground} / ${background}`,
90
+ severity: "warning",
91
+ };
92
+ }
93
+ const label = pair.name ? `${pair.name} (${foreground} on ${background})` : `${foreground} on ${background}`;
94
+ if (ratio < WCAG_AA_NORMAL) {
95
+ return {
96
+ kind: "contrast",
97
+ summary: `${label}: contrast ${ratio.toFixed(2)}:1 below WCAG AA 4.5:1`,
98
+ severity: "error",
99
+ };
100
+ }
101
+ return {
102
+ kind: "contrast",
103
+ summary: `${label}: contrast ${ratio.toFixed(2)}:1 meets WCAG AA`,
104
+ severity: "info",
105
+ };
106
+ };
107
+ const contrastSensor = {
108
+ name: "contrast",
109
+ async run(input) {
110
+ const pairs = discoverPairs(input);
111
+ if (pairs.length === 0)
112
+ return [];
113
+ return pairs.map(scorePair);
114
+ },
115
+ };
116
+ exports.default = contrastSensor;
117
+ //# sourceMappingURL=contrast.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contrast.js","sourceRoot":"","sources":["../../src/sensors/contrast.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import type { SensorName } from "../engine/detect";
2
+ export interface SensorFinding {
3
+ kind: "screenshot" | "a11y" | "contrast" | "vision";
4
+ path?: string;
5
+ summary: string;
6
+ severity: "info" | "warning" | "error";
7
+ }
8
+ export interface ColorPair {
9
+ name?: string;
10
+ foreground: string;
11
+ background: string;
12
+ }
13
+ export interface SensorInput {
14
+ cwd: string;
15
+ ridgelineDir?: string;
16
+ buildDir?: string;
17
+ shapeMdPath?: string;
18
+ artifactsDir?: string;
19
+ model?: string;
20
+ url?: string;
21
+ screenshotPath?: string;
22
+ contrastPairs?: readonly ColorPair[];
23
+ }
24
+ export interface SensorAdapter {
25
+ readonly name: SensorName;
26
+ run(input: SensorInput): Promise<SensorFinding[]>;
27
+ }
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/sensors/index.ts"],"names":[],"mappings":""}
@@ -0,0 +1,69 @@
1
+ import type { SensorAdapter, SensorFinding, SensorInput } from "./index";
2
+ export declare const PROBE_PORTS: readonly number[];
3
+ type PortResult = {
4
+ source: "shape-md";
5
+ port: number;
6
+ } | {
7
+ source: "probe";
8
+ port: number;
9
+ attempts: readonly number[];
10
+ } | {
11
+ source: "none";
12
+ attempts: readonly number[];
13
+ reason: "no-probe-match" | "malformed-declaration";
14
+ };
15
+ interface ParseResult {
16
+ port: number | null;
17
+ malformed: boolean;
18
+ }
19
+ export declare const parsePortFromShape: (content: string) => ParseResult;
20
+ interface ProbeOptions {
21
+ timeoutPerProbeMs?: number;
22
+ totalTimeoutMs?: number;
23
+ probe?: (port: number, timeoutMs: number) => Promise<boolean>;
24
+ ports?: readonly number[];
25
+ }
26
+ export declare const probeDevServer: (options?: ProbeOptions) => Promise<{
27
+ port: number | null;
28
+ attempts: readonly number[];
29
+ }>;
30
+ export declare const resolveDevServerPort: (input: SensorInput, options?: ProbeOptions) => Promise<PortResult>;
31
+ interface PlaywrightModule {
32
+ chromium: {
33
+ launch(options: {
34
+ args?: string[];
35
+ timeout?: number;
36
+ headless?: boolean;
37
+ }): Promise<PlaywrightBrowser>;
38
+ };
39
+ }
40
+ interface PlaywrightBrowser {
41
+ newPage(): Promise<PlaywrightPage>;
42
+ close(): Promise<void>;
43
+ }
44
+ interface PlaywrightPage {
45
+ goto(url: string, options?: {
46
+ timeout?: number;
47
+ waitUntil?: string;
48
+ }): Promise<unknown>;
49
+ screenshot(options: {
50
+ path: string;
51
+ fullPage?: boolean;
52
+ }): Promise<Buffer>;
53
+ close(): Promise<void>;
54
+ addScriptTag(options: {
55
+ path: string;
56
+ }): Promise<unknown>;
57
+ evaluate<R>(fn: string | (() => R)): Promise<R>;
58
+ }
59
+ type LoadPlaywright = () => PlaywrightModule;
60
+ interface PlaywrightRunInternals {
61
+ loadPlaywright?: LoadPlaywright;
62
+ isSandboxed?: () => boolean;
63
+ isResolvable?: () => boolean;
64
+ probeOptions?: ProbeOptions;
65
+ launchTimeoutMs?: number;
66
+ }
67
+ export declare const runPlaywrightSensor: (input: SensorInput, internals?: PlaywrightRunInternals) => Promise<SensorFinding[]>;
68
+ declare const playwrightSensor: SensorAdapter;
69
+ export default playwrightSensor;
@@ -0,0 +1,266 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.runPlaywrightSensor = exports.resolveDevServerPort = exports.probeDevServer = exports.parsePortFromShape = exports.PROBE_PORTS = void 0;
37
+ const fs = __importStar(require("node:fs"));
38
+ const http = __importStar(require("node:http"));
39
+ const path = __importStar(require("node:path"));
40
+ const PLAYWRIGHT_INSTALL_HINT = "npm install --save-dev playwright && npx playwright install chromium";
41
+ const isPlaywrightResolvable = () => {
42
+ try {
43
+ require.resolve("playwright");
44
+ return true;
45
+ }
46
+ catch {
47
+ return false;
48
+ }
49
+ };
50
+ const LAUNCH_TIMEOUT_MS = 10_000;
51
+ const DEFAULT_PROBE_TIMEOUT_MS = 250;
52
+ const DEFAULT_TOTAL_PROBE_MS = 1_000;
53
+ const RUNTIME_BLOCK_RE = /^##\s+Runtime\s*$([\s\S]*?)(?=^##\s+|$(?![\r\n]))/m;
54
+ const DEV_PORT_LINE_RE = /^\s*-\s*\*\*Dev server port:\*\*\s+(\d+)\s*$/m;
55
+ const DEV_PORT_LINE_GLOBAL = new RegExp(DEV_PORT_LINE_RE.source, "gm");
56
+ exports.PROBE_PORTS = [5173, 3000, 8080, 4321];
57
+ const parsePortFromShape = (content) => {
58
+ const runtimeBlocks = [];
59
+ const blockRe = new RegExp(RUNTIME_BLOCK_RE.source, "gm");
60
+ let match;
61
+ while ((match = blockRe.exec(content)) !== null) {
62
+ runtimeBlocks.push(match[1] ?? "");
63
+ }
64
+ if (runtimeBlocks.length === 0)
65
+ return { port: null, malformed: false };
66
+ if (runtimeBlocks.length > 1)
67
+ return { port: null, malformed: true };
68
+ const block = runtimeBlocks[0];
69
+ const ports = [];
70
+ let m;
71
+ const globalRe = new RegExp(DEV_PORT_LINE_GLOBAL.source, "gm");
72
+ while ((m = globalRe.exec(block)) !== null) {
73
+ const n = parseInt(m[1], 10);
74
+ if (Number.isFinite(n) && n >= 1 && n <= 65535) {
75
+ ports.push(n);
76
+ }
77
+ else {
78
+ return { port: null, malformed: true };
79
+ }
80
+ }
81
+ if (ports.length === 0)
82
+ return { port: null, malformed: false };
83
+ if (ports.length > 1)
84
+ return { port: null, malformed: true };
85
+ return { port: ports[0], malformed: false };
86
+ };
87
+ exports.parsePortFromShape = parsePortFromShape;
88
+ const headProbe = (port, timeoutMs) => new Promise((resolve) => {
89
+ const req = http.request({ host: "127.0.0.1", port, method: "HEAD", path: "/", timeout: timeoutMs }, (res) => {
90
+ res.resume();
91
+ resolve(true);
92
+ });
93
+ req.on("timeout", () => {
94
+ req.destroy();
95
+ resolve(false);
96
+ });
97
+ req.on("error", () => resolve(false));
98
+ req.end();
99
+ });
100
+ const probeDevServer = async (options = {}) => {
101
+ const perProbe = options.timeoutPerProbeMs ?? DEFAULT_PROBE_TIMEOUT_MS;
102
+ const total = options.totalTimeoutMs ?? DEFAULT_TOTAL_PROBE_MS;
103
+ const probeFn = options.probe ?? headProbe;
104
+ const ports = options.ports ?? exports.PROBE_PORTS;
105
+ const attempts = [];
106
+ const start = Date.now();
107
+ for (const port of ports) {
108
+ if (Date.now() - start >= total)
109
+ break;
110
+ attempts.push(port);
111
+ const ok = await probeFn(port, perProbe).catch(() => false);
112
+ if (ok)
113
+ return { port, attempts };
114
+ }
115
+ return { port: null, attempts };
116
+ };
117
+ exports.probeDevServer = probeDevServer;
118
+ const readShapeMd = (input) => {
119
+ const candidate = input.shapeMdPath ??
120
+ (input.buildDir ? path.join(input.buildDir, "shape.md") : null);
121
+ if (!candidate)
122
+ return null;
123
+ if (!fs.existsSync(candidate))
124
+ return null;
125
+ try {
126
+ return fs.readFileSync(candidate, "utf-8");
127
+ }
128
+ catch {
129
+ return null;
130
+ }
131
+ };
132
+ const logWarn = (line) => {
133
+ process.stderr.write(`${line}\n`);
134
+ };
135
+ const resolveDevServerPort = async (input, options = {}) => {
136
+ const shape = readShapeMd(input);
137
+ if (shape) {
138
+ const parsed = (0, exports.parsePortFromShape)(shape);
139
+ if (parsed.port !== null) {
140
+ return { source: "shape-md", port: parsed.port };
141
+ }
142
+ if (parsed.malformed) {
143
+ logWarn(`[ridgeline] WARN: shape.md ## Runtime has malformed dev-server port; falling back to probing`);
144
+ }
145
+ }
146
+ const { port, attempts } = await (0, exports.probeDevServer)(options);
147
+ if (port === null) {
148
+ return { source: "none", attempts, reason: "no-probe-match" };
149
+ }
150
+ return { source: "probe", port, attempts };
151
+ };
152
+ exports.resolveDevServerPort = resolveDevServerPort;
153
+ const isSandboxDetected = (env = process.env) => {
154
+ if (env.RIDGELINE_SANDBOX)
155
+ return true;
156
+ if (env.GREYWALL_ACTIVE)
157
+ return true;
158
+ if (env.BWRAP_DETECTED)
159
+ return true;
160
+ if (env.container)
161
+ return true;
162
+ return false;
163
+ };
164
+ const defaultLoadPlaywright = () => require("playwright");
165
+ const unresolvableFinding = () => ({
166
+ kind: "screenshot",
167
+ severity: "warning",
168
+ summary: `Playwright is not installed. Install with: ${PLAYWRIGHT_INSTALL_HINT}`,
169
+ });
170
+ const launchFailureFinding = (message) => ({
171
+ kind: "screenshot",
172
+ severity: "warning",
173
+ summary: `Chromium launch failed — sandbox-incompatible (${message})`,
174
+ });
175
+ const noDevServerFinding = (attempts) => ({
176
+ kind: "screenshot",
177
+ severity: "warning",
178
+ summary: `no dev server detected (probed ports: ${attempts.join(", ") || "none"})`,
179
+ });
180
+ const runPlaywrightSensor = async (input, internals = {}) => {
181
+ const resolvable = (internals.isResolvable ?? isPlaywrightResolvable)();
182
+ if (!resolvable) {
183
+ return [unresolvableFinding()];
184
+ }
185
+ const port = await (0, exports.resolveDevServerPort)(input, internals.probeOptions).catch(() => ({
186
+ source: "none",
187
+ attempts: [],
188
+ reason: "no-probe-match",
189
+ }));
190
+ if (port.source === "none") {
191
+ return [noDevServerFinding(port.attempts)];
192
+ }
193
+ const load = internals.loadPlaywright ?? defaultLoadPlaywright;
194
+ const sandboxed = (internals.isSandboxed ?? isSandboxDetected)();
195
+ const launchTimeout = internals.launchTimeoutMs ?? LAUNCH_TIMEOUT_MS;
196
+ const launchArgs = sandboxed ? ["--no-sandbox", "--disable-setuid-sandbox"] : [];
197
+ let playwright;
198
+ try {
199
+ playwright = load();
200
+ }
201
+ catch (err) {
202
+ const message = err instanceof Error ? err.message : String(err);
203
+ if (message.toLowerCase().includes("cannot find module")) {
204
+ return [unresolvableFinding()];
205
+ }
206
+ return [launchFailureFinding(message)];
207
+ }
208
+ let browser;
209
+ try {
210
+ browser = await playwright.chromium.launch({
211
+ args: launchArgs,
212
+ timeout: launchTimeout,
213
+ headless: true,
214
+ });
215
+ }
216
+ catch (err) {
217
+ const message = err instanceof Error ? err.message : String(err);
218
+ if (/executable doesn.?t exist|browser not found|playwright install/i.test(message)) {
219
+ return [unresolvableFinding()];
220
+ }
221
+ return [launchFailureFinding(message)];
222
+ }
223
+ const artifactsDir = input.artifactsDir ??
224
+ (input.buildDir ? path.join(input.buildDir, "artifacts") : path.join(input.cwd, ".ridgeline", "artifacts"));
225
+ try {
226
+ fs.mkdirSync(artifactsDir, { recursive: true });
227
+ }
228
+ catch {
229
+ // directory creation failed — fall through; screenshot will fail non-fatally
230
+ }
231
+ const screenshotPath = path.join(artifactsDir, `screenshot-${Date.now()}.png`);
232
+ const url = input.url ?? `http://127.0.0.1:${port.port}`;
233
+ try {
234
+ const page = await browser.newPage();
235
+ await page.goto(url, { waitUntil: "load", timeout: launchTimeout });
236
+ await page.screenshot({ path: screenshotPath, fullPage: true });
237
+ await page.close();
238
+ }
239
+ catch (err) {
240
+ await browser.close().catch(() => { });
241
+ const message = err instanceof Error ? err.message : String(err);
242
+ return [
243
+ {
244
+ kind: "screenshot",
245
+ severity: "warning",
246
+ summary: `screenshot failed at ${url}: ${message}`,
247
+ },
248
+ ];
249
+ }
250
+ await browser.close().catch(() => { });
251
+ return [
252
+ {
253
+ kind: "screenshot",
254
+ severity: "info",
255
+ path: screenshotPath,
256
+ summary: `captured screenshot of ${url} (port source: ${port.source})`,
257
+ },
258
+ ];
259
+ };
260
+ exports.runPlaywrightSensor = runPlaywrightSensor;
261
+ const playwrightSensor = {
262
+ name: "playwright",
263
+ run: (input) => (0, exports.runPlaywrightSensor)(input),
264
+ };
265
+ exports.default = playwrightSensor;
266
+ //# sourceMappingURL=playwright.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"playwright.js","sourceRoot":"","sources":["../../src/sensors/playwright.ts"],"names":[],"mappings":"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"}