@pretorian-worx/runclaudia-cli 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Paul Schneider
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,49 @@
1
+ # @pretorian-worx/runclaudia-cli
2
+
3
+ The CLI for [claudia](https://github.com/pretorian-worx/runclaudia) — a diff-aware post-deploy test agent. Picks the relevant subset of your Playwright suite for a given diff, runs it against the deployed production URL, and reports the result to GitHub Actions, the merged PR, and Slack.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npx -y @pretorian-worx/runclaudia-cli <subcommand> [args]
9
+ ```
10
+
11
+ Or globally:
12
+
13
+ ```bash
14
+ npm i -g @pretorian-worx/runclaudia-cli
15
+ claudia <subcommand> [args]
16
+ ```
17
+
18
+ ## Subcommands
19
+
20
+ - `claudia plan` — diff-aware test plan generation (uses Anthropic)
21
+ - `claudia map` — build/inspect the route + endpoint + infra + DB + spec map
22
+ - `claudia select` — pick a diff-relevant subset of Playwright/Cypress specs
23
+ - `claudia run` — `select` + execute the subset against a deployed URL
24
+ - `claudia ratings` — aggregate 👍/👎 reactions across PR plan comments
25
+
26
+ `claudia plan` requires `ANTHROPIC_API_KEY` in the environment. All other subcommands are deterministic local code (zero API calls).
27
+
28
+ ## Post-deploy verification
29
+
30
+ This is the canonical use:
31
+
32
+ ```bash
33
+ npx -y @pretorian-worx/runclaudia-cli run \
34
+ --base $LAST_DEPLOY_SHA \
35
+ --head $JUST_DEPLOYED_SHA \
36
+ --target https://app.example.com \
37
+ --slack-webhook $SLACK_WEBHOOK_URL
38
+ ```
39
+
40
+ Result is auto-reported to:
41
+ - `$GITHUB_STEP_SUMMARY` when running in GitHub Actions
42
+ - A sticky comment on the merged PR that introduced the deployed commit
43
+ - Slack (if `--slack-webhook` or `CLAUDIA_SLACK_WEBHOOK` is set)
44
+
45
+ See the [main repo README](https://github.com/pretorian-worx/runclaudia#readme) for the full workflow example and the larger product context.
46
+
47
+ ## License
48
+
49
+ MIT
@@ -0,0 +1,7 @@
1
+ export interface ClaudiaConfig {
2
+ rootDir?: string;
3
+ defaultBase?: string;
4
+ model?: string;
5
+ cachePath?: string;
6
+ }
7
+ export declare function loadConfig(cwd: string): Promise<ClaudiaConfig>;
package/dist/config.js ADDED
@@ -0,0 +1,22 @@
1
+ import { existsSync } from "node:fs";
2
+ import { pathToFileURL } from "node:url";
3
+ import { join, resolve } from "node:path";
4
+ const CANDIDATES = ["claudia.config.ts", "claudia.config.js", "claudia.config.mjs"];
5
+ export async function loadConfig(cwd) {
6
+ for (const name of CANDIDATES) {
7
+ const abs = resolve(cwd, name);
8
+ if (!existsSync(abs))
9
+ continue;
10
+ try {
11
+ const mod = await import(pathToFileURL(abs).href);
12
+ const cfg = (mod.default ?? mod);
13
+ return cfg ?? {};
14
+ }
15
+ catch {
16
+ return {};
17
+ }
18
+ }
19
+ void join;
20
+ return {};
21
+ }
22
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAS1C,MAAM,UAAU,GAAG,CAAC,mBAAmB,EAAE,mBAAmB,EAAE,oBAAoB,CAAC,CAAC;AAEpF,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,GAAW;IAC1C,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;QAC9B,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAC/B,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,SAAS;QAC/B,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;YAClD,MAAM,GAAG,GAAG,CAAC,GAAG,CAAC,OAAO,IAAI,GAAG,CAAkB,CAAC;YAClD,OAAO,GAAG,IAAI,EAAE,CAAC;QACnB,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC;IACD,KAAK,IAAI,CAAC;IACV,OAAO,EAAE,CAAC;AACZ,CAAC"}
@@ -0,0 +1 @@
1
+ export { formatPlanMarkdown as formatMarkdown, formatPlanJson as formatJson } from "@pretorian-worx/runclaudia-core";
package/dist/format.js ADDED
@@ -0,0 +1,5 @@
1
+ // Compatibility re-export. The real renderers moved to @pretorian-worx/runclaudia-core in v0.11
2
+ // so the GitHub Action can import them without reaching into the CLI's dist/.
3
+ // New code should import directly from "@pretorian-worx/runclaudia-core".
4
+ export { formatPlanMarkdown as formatMarkdown, formatPlanJson as formatJson } from "@pretorian-worx/runclaudia-core";
5
+ //# sourceMappingURL=format.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.js","sourceRoot":"","sources":["../src/format.ts"],"names":[],"mappings":"AAAA,gGAAgG;AAChG,8EAA8E;AAC9E,0EAA0E;AAC1E,OAAO,EAAE,kBAAkB,IAAI,cAAc,EAAE,cAAc,IAAI,UAAU,EAAE,MAAM,iCAAiC,CAAC"}
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,272 @@
1
+ #!/usr/bin/env node
2
+ import { defineCommand, runMain } from "citty";
3
+ import { resolve } from "node:path";
4
+ import { writeFileSync } from "node:fs";
5
+ import { execFileSync, spawn } from "node:child_process";
6
+ import { mkdtempSync, readFileSync, existsSync } from "node:fs";
7
+ import { tmpdir } from "node:os";
8
+ import { join } from "node:path";
9
+ import { buildPlaywrightCommand, formatRunMarkdown, formatSelectionMarkdown, loadOrBuildMap, parsePlaywrightReport, PlannerError, runPlan, runSelect, } from "@pretorian-worx/runclaudia-core";
10
+ import { formatJson, formatMarkdown } from "./format.js";
11
+ import { loadConfig } from "./config.js";
12
+ import { aggregateRatings, formatRatings } from "./ratings.js";
13
+ import { dispatchReporters } from "./reporters.js";
14
+ const planCmd = defineCommand({
15
+ meta: { name: "plan", description: "Produce a diff-aware test plan" },
16
+ args: {
17
+ base: { type: "string", required: true, description: "Base ref (e.g. main or a SHA)" },
18
+ head: { type: "string", default: "HEAD", description: "Head ref" },
19
+ cwd: { type: "string", description: "Project root directory" },
20
+ target: { type: "string", description: "Deployed URL the plan will reference" },
21
+ json: { type: "boolean", description: "Emit JSON instead of markdown" },
22
+ model: { type: "string", description: "Override the planner model" },
23
+ output: { type: "string", description: "Write output to a file as well as stdout" },
24
+ "refresh-map": { type: "boolean", description: "Force a fresh route-map build" },
25
+ },
26
+ async run({ args }) {
27
+ const rootDir = resolve(args.cwd ?? process.cwd());
28
+ const cfg = await loadConfig(rootDir);
29
+ let result;
30
+ try {
31
+ result = await runPlan({
32
+ rootDir: cfg.rootDir ? resolve(rootDir, cfg.rootDir) : rootDir,
33
+ base: args.base,
34
+ head: args.head,
35
+ targetUrl: args.target,
36
+ refreshMap: Boolean(args["refresh-map"]),
37
+ model: args.model ?? cfg.model,
38
+ });
39
+ }
40
+ catch (err) {
41
+ if (err instanceof PlannerError) {
42
+ process.stderr.write(`claudia: ${err.message}\n`);
43
+ process.stderr.write(JSON.stringify(err.details, null, 2) + "\n");
44
+ process.exit(2);
45
+ }
46
+ throw err;
47
+ }
48
+ const text = args.json ? formatJson(result) : formatMarkdown(result);
49
+ process.stdout.write(text + "\n");
50
+ if (args.output)
51
+ writeFileSync(resolve(args.output), text + "\n", "utf8");
52
+ if (result.plan.verdict === "skip")
53
+ process.exit(0);
54
+ },
55
+ });
56
+ const mapCmd = defineCommand({
57
+ meta: { name: "map", description: "Build or inspect the route map" },
58
+ args: {
59
+ cwd: { type: "string", description: "Project root directory" },
60
+ refresh: { type: "boolean", description: "Rebuild even if cache is fresh" },
61
+ json: { type: "boolean", description: "Print full map as JSON" },
62
+ },
63
+ async run({ args }) {
64
+ const rootDir = resolve(args.cwd ?? process.cwd());
65
+ const map = loadOrBuildMap({ rootDir, refresh: Boolean(args.refresh) });
66
+ if (args.json) {
67
+ process.stdout.write(JSON.stringify(map, null, 2) + "\n");
68
+ return;
69
+ }
70
+ process.stdout.write(`framework: ${map.framework}\nroutes: ${map.routes.length}\n`);
71
+ for (const r of map.routes)
72
+ process.stdout.write(` ${r.route} (${r.files.length} files)\n`);
73
+ },
74
+ });
75
+ const selectCmd = defineCommand({
76
+ meta: {
77
+ name: "select",
78
+ description: "Pick the subset of the user's existing Playwright/Cypress specs that cover the routes/endpoints implicated by a diff. Intended for post-deploy verification workflows.",
79
+ },
80
+ args: {
81
+ base: { type: "string", required: true, description: "Base ref (the last-deployed SHA)" },
82
+ head: { type: "string", default: "HEAD", description: "Head ref (the just-deployed SHA)" },
83
+ cwd: { type: "string", description: "Project root directory" },
84
+ json: { type: "boolean", description: "Emit JSON instead of markdown" },
85
+ "refresh-map": { type: "boolean", description: "Force a fresh map build" },
86
+ "grep-only": {
87
+ type: "boolean",
88
+ description: "Print just the Playwright --grep pattern (empty if no eligible specs)",
89
+ },
90
+ "files-only": {
91
+ type: "boolean",
92
+ description: "Print just the selected spec file paths, one per line",
93
+ },
94
+ },
95
+ run({ args }) {
96
+ const rootDir = resolve(args.cwd ?? process.cwd());
97
+ const result = runSelect({
98
+ rootDir,
99
+ base: args.base,
100
+ head: args.head,
101
+ refreshMap: Boolean(args["refresh-map"]),
102
+ });
103
+ if (args["grep-only"]) {
104
+ process.stdout.write((result.playwrightGrep ?? "") + "\n");
105
+ return;
106
+ }
107
+ if (args["files-only"]) {
108
+ for (const s of result.selected)
109
+ process.stdout.write(s.file + "\n");
110
+ return;
111
+ }
112
+ if (args.json) {
113
+ process.stdout.write(JSON.stringify(result, null, 2) + "\n");
114
+ return;
115
+ }
116
+ process.stdout.write(formatSelectionMarkdown(result, { base: args.base, head: args.head }) + "\n");
117
+ },
118
+ });
119
+ const runCmd = defineCommand({
120
+ meta: {
121
+ name: "run",
122
+ description: "Select + execute Playwright specs covering the diff against a deployed target URL. Intended for post-deploy verification workflows.",
123
+ },
124
+ args: {
125
+ base: { type: "string", required: true, description: "Base ref (the last-deployed SHA)" },
126
+ head: { type: "string", default: "HEAD", description: "Head ref (the just-deployed SHA)" },
127
+ target: { type: "string", required: true, description: "Deployed URL to run specs against (PLAYWRIGHT_BASE_URL)" },
128
+ cwd: { type: "string", description: "Project root directory" },
129
+ "playwright-config": { type: "string", description: "Path to Playwright config file" },
130
+ "refresh-map": { type: "boolean", description: "Force a fresh map build" },
131
+ json: { type: "boolean", description: "Emit JSON summary instead of markdown" },
132
+ "dry-run": { type: "boolean", description: "Print the command that would run; don't spawn it" },
133
+ "slack-webhook": {
134
+ type: "string",
135
+ description: "Slack incoming-webhook URL to POST the result to (or set CLAUDIA_SLACK_WEBHOOK)",
136
+ },
137
+ "no-step-summary": {
138
+ type: "boolean",
139
+ description: "Disable auto-writing to $GITHUB_STEP_SUMMARY when running in GitHub Actions",
140
+ },
141
+ "no-pr-comment": {
142
+ type: "boolean",
143
+ description: "Disable posting a sticky comment back to the merged PR for this SHA",
144
+ },
145
+ },
146
+ async run({ args }) {
147
+ const rootDir = resolve(args.cwd ?? process.cwd());
148
+ const selection = runSelect({
149
+ rootDir,
150
+ base: args.base,
151
+ head: args.head,
152
+ refreshMap: Boolean(args["refresh-map"]),
153
+ });
154
+ const tmpDir = mkdtempSync(join(tmpdir(), "claudia-run-"));
155
+ const jsonReportPath = join(tmpDir, "report.json");
156
+ const cmd = buildPlaywrightCommand({
157
+ selection,
158
+ target: args.target,
159
+ playwrightConfig: args["playwright-config"],
160
+ jsonReportPath,
161
+ });
162
+ if (!cmd) {
163
+ const md = formatRunMarkdown({
164
+ selection,
165
+ report: null,
166
+ target: args.target,
167
+ nothingToRun: true,
168
+ });
169
+ if (args.json) {
170
+ process.stdout.write(JSON.stringify({ status: "nothing-to-run", selection }, null, 2) + "\n");
171
+ }
172
+ else {
173
+ process.stdout.write(md + "\n");
174
+ }
175
+ return;
176
+ }
177
+ if (args["dry-run"]) {
178
+ process.stdout.write(`${cmd.command} ${cmd.args.join(" ")}\n`);
179
+ for (const [k, v] of Object.entries(cmd.env))
180
+ process.stdout.write(` ${k}=${v}\n`);
181
+ return;
182
+ }
183
+ process.stderr.write(`claudia: running ${cmd.command} ${cmd.args.join(" ")}\n`);
184
+ const child = spawn(cmd.command, cmd.args, {
185
+ cwd: rootDir,
186
+ env: { ...process.env, ...cmd.env },
187
+ stdio: ["ignore", "inherit", "inherit"],
188
+ });
189
+ const exitCode = await new Promise((resolveCode) => {
190
+ child.on("close", (code) => resolveCode(code ?? 1));
191
+ child.on("error", (err) => {
192
+ process.stderr.write(`claudia: failed to spawn Playwright: ${err.message}\n`);
193
+ resolveCode(127);
194
+ });
195
+ });
196
+ let report = null;
197
+ if (existsSync(jsonReportPath)) {
198
+ try {
199
+ const raw = JSON.parse(readFileSync(jsonReportPath, "utf8"));
200
+ report = parsePlaywrightReport(raw);
201
+ }
202
+ catch (err) {
203
+ process.stderr.write(`claudia: could not parse Playwright JSON report (${err instanceof Error ? err.message : String(err)})\n`);
204
+ }
205
+ }
206
+ const markdown = formatRunMarkdown({
207
+ selection,
208
+ report,
209
+ target: args.target,
210
+ nothingToRun: false,
211
+ });
212
+ if (args.json) {
213
+ process.stdout.write(JSON.stringify({ status: report ? "completed" : "no-report", exitCode, report }, null, 2) + "\n");
214
+ }
215
+ else {
216
+ process.stdout.write(markdown + "\n");
217
+ }
218
+ // Resolve the SHA we just verified so reporters can find the originating PR.
219
+ const headSha = resolveSha(rootDir, args.head);
220
+ await dispatchReporters({
221
+ markdown,
222
+ headSha,
223
+ passed: report ? report.failed === 0 : exitCode === 0,
224
+ }, {
225
+ slackWebhook: args["slack-webhook"],
226
+ disableStepSummary: Boolean(args["no-step-summary"]),
227
+ disablePrComment: Boolean(args["no-pr-comment"]),
228
+ });
229
+ process.exit(exitCode);
230
+ },
231
+ });
232
+ function resolveSha(cwd, ref) {
233
+ try {
234
+ return execFileSync("git", ["rev-parse", ref], { cwd, encoding: "utf8" }).trim();
235
+ }
236
+ catch {
237
+ return ref;
238
+ }
239
+ }
240
+ const ratingsCmd = defineCommand({
241
+ meta: { name: "ratings", description: "Aggregate 👍/👎 reactions on claudia comments across a repo's PRs" },
242
+ args: {
243
+ repo: { type: "string", required: true, description: "owner/name (e.g. pretorian-worx/runclaudia)" },
244
+ limit: { type: "string", description: "Max PRs to scan (default 100)" },
245
+ state: { type: "string", description: "open | closed | all (default all)" },
246
+ json: { type: "boolean", description: "Emit JSON instead of markdown" },
247
+ },
248
+ run({ args }) {
249
+ const state = args.state;
250
+ if (state && !["open", "closed", "all"].includes(state)) {
251
+ process.stderr.write(`Invalid --state: ${state}\n`);
252
+ process.exit(2);
253
+ }
254
+ const summary = aggregateRatings({
255
+ repo: args.repo,
256
+ limit: args.limit ? parseInt(args.limit, 10) : undefined,
257
+ state,
258
+ });
259
+ if (args.json) {
260
+ process.stdout.write(JSON.stringify(summary, null, 2) + "\n");
261
+ }
262
+ else {
263
+ process.stdout.write(formatRatings(summary) + "\n");
264
+ }
265
+ },
266
+ });
267
+ const main = defineCommand({
268
+ meta: { name: "claudia", description: "Diff-aware post-deploy test agent" },
269
+ subCommands: { plan: planCmd, map: mapCmd, select: selectCmd, run: runCmd, ratings: ratingsCmd },
270
+ });
271
+ runMain(main);
272
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ export interface PRRating {
2
+ prNumber: number;
3
+ url: string;
4
+ thumbsUp: number;
5
+ thumbsDown: number;
6
+ verdict: "useful" | "not_useful" | "no_signal";
7
+ }
8
+ export interface RatingsSummary {
9
+ repo: string;
10
+ total: number;
11
+ useful: number;
12
+ notUseful: number;
13
+ noSignal: number;
14
+ usefulPercent: number | null;
15
+ perPR: PRRating[];
16
+ }
17
+ export interface RatingsOptions {
18
+ repo: string;
19
+ limit?: number;
20
+ state?: "open" | "closed" | "all";
21
+ }
22
+ /**
23
+ * Aggregates 👍 / 👎 reactions on claudia's sticky comments across a repo's
24
+ * pull requests. Only +1 and -1 from non-bot users count; everything else
25
+ * (laugh, hooray, confused, heart, rocket, eyes, or reactions from the
26
+ * github-actions bot itself) is ignored.
27
+ */
28
+ export declare function aggregateRatings(opts: RatingsOptions): RatingsSummary;
29
+ export declare function formatRatings(s: RatingsSummary): string;
@@ -0,0 +1,91 @@
1
+ import { execFileSync } from "node:child_process";
2
+ const MARKER = "<!-- claudia:plan -->";
3
+ /**
4
+ * Aggregates 👍 / 👎 reactions on claudia's sticky comments across a repo's
5
+ * pull requests. Only +1 and -1 from non-bot users count; everything else
6
+ * (laugh, hooray, confused, heart, rocket, eyes, or reactions from the
7
+ * github-actions bot itself) is ignored.
8
+ */
9
+ export function aggregateRatings(opts) {
10
+ const limit = opts.limit ?? 100;
11
+ const state = opts.state ?? "all";
12
+ const prs = ghJson(["pr", "list", "-R", opts.repo, "--state", state, "--limit", String(limit), "--json", "number,url"]);
13
+ const perPR = [];
14
+ for (const pr of prs) {
15
+ const comments = ghJson([
16
+ "api",
17
+ `repos/${opts.repo}/issues/${pr.number}/comments`,
18
+ "--paginate",
19
+ "--jq",
20
+ "[.[] | {id, body}]",
21
+ ]);
22
+ const claudiaComment = comments.find((c) => c.body?.includes(MARKER));
23
+ if (!claudiaComment)
24
+ continue;
25
+ const reactions = ghJson([
26
+ "api",
27
+ `repos/${opts.repo}/issues/comments/${claudiaComment.id}/reactions`,
28
+ "--paginate",
29
+ "--jq",
30
+ "[.[] | {content, user: {login: .user.login}}]",
31
+ ]);
32
+ const thumbsUp = countReactions(reactions, "+1");
33
+ const thumbsDown = countReactions(reactions, "-1");
34
+ const verdict = thumbsUp + thumbsDown === 0
35
+ ? "no_signal"
36
+ : thumbsUp > thumbsDown
37
+ ? "useful"
38
+ : "not_useful";
39
+ perPR.push({ prNumber: pr.number, url: pr.url, thumbsUp, thumbsDown, verdict });
40
+ }
41
+ const useful = perPR.filter((p) => p.verdict === "useful").length;
42
+ const notUseful = perPR.filter((p) => p.verdict === "not_useful").length;
43
+ const noSignal = perPR.filter((p) => p.verdict === "no_signal").length;
44
+ const ratedTotal = useful + notUseful;
45
+ return {
46
+ repo: opts.repo,
47
+ total: perPR.length,
48
+ useful,
49
+ notUseful,
50
+ noSignal,
51
+ usefulPercent: ratedTotal === 0 ? null : (useful / ratedTotal) * 100,
52
+ perPR,
53
+ };
54
+ }
55
+ function countReactions(reactions, wanted) {
56
+ // Ignore the github-actions bot's own seeded reactions; we want real user signal.
57
+ return reactions.filter((r) => r.content === wanted && r.user?.login && r.user.login !== "github-actions[bot]").length;
58
+ }
59
+ function ghJson(args) {
60
+ try {
61
+ const raw = execFileSync("gh", args, { encoding: "utf8", maxBuffer: 16 * 1024 * 1024 });
62
+ return JSON.parse(raw);
63
+ }
64
+ catch (err) {
65
+ const msg = err instanceof Error ? err.message : String(err);
66
+ throw new Error(`gh ${args.join(" ")}: ${msg}`);
67
+ }
68
+ }
69
+ export function formatRatings(s) {
70
+ const lines = [];
71
+ lines.push(`# claudia ratings — ${s.repo}`);
72
+ lines.push("");
73
+ if (s.total === 0) {
74
+ lines.push("No claudia comments found in this repo.");
75
+ return lines.join("\n");
76
+ }
77
+ lines.push(`PRs with a claudia comment: **${s.total}**`);
78
+ lines.push(`- 👍 useful: ${s.useful}`);
79
+ lines.push(`- 👎 not useful: ${s.notUseful}`);
80
+ lines.push(`- ⚪ no signal: ${s.noSignal}`);
81
+ if (s.usefulPercent !== null) {
82
+ lines.push("");
83
+ lines.push(`**Useful%: ${s.usefulPercent.toFixed(1)}%** (of ${s.useful + s.notUseful} rated PRs)`);
84
+ }
85
+ else {
86
+ lines.push("");
87
+ lines.push("No 👍/👎 reactions yet — no useful% to report.");
88
+ }
89
+ return lines.join("\n");
90
+ }
91
+ //# sourceMappingURL=ratings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ratings.js","sourceRoot":"","sources":["../src/ratings.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ export interface ReportContext {
2
+ /** Pre-rendered markdown summary of the verification run. */
3
+ markdown: string;
4
+ /** SHA whose deployment was verified. Used to look up the originating PR. */
5
+ headSha: string;
6
+ /** Whether the verification passed overall. */
7
+ passed: boolean;
8
+ /** Repo identifier "owner/name". Auto-detected from GITHUB_REPOSITORY when not set. */
9
+ repo?: string;
10
+ }
11
+ export interface ReporterOptions {
12
+ slackWebhook?: string;
13
+ disableStepSummary?: boolean;
14
+ disablePrComment?: boolean;
15
+ }
16
+ export declare function dispatchReporters(ctx: ReportContext, opts?: ReporterOptions): Promise<void>;
@@ -0,0 +1,127 @@
1
+ import { appendFileSync } from "node:fs";
2
+ import { execFileSync } from "node:child_process";
3
+ const STICKY_MARKER = "<!-- claudia:verify -->";
4
+ export async function dispatchReporters(ctx, opts = {}) {
5
+ await Promise.allSettled([
6
+ writeStepSummary(ctx, opts),
7
+ backCommentOnMergedPr(ctx, opts),
8
+ postToSlack(ctx, opts),
9
+ ]);
10
+ }
11
+ // ---------- 1. $GITHUB_STEP_SUMMARY ----------
12
+ async function writeStepSummary(ctx, opts) {
13
+ if (opts.disableStepSummary)
14
+ return;
15
+ const file = process.env.GITHUB_STEP_SUMMARY;
16
+ if (!file)
17
+ return;
18
+ try {
19
+ appendFileSync(file, ctx.markdown + "\n", "utf8");
20
+ }
21
+ catch (err) {
22
+ warn("step-summary", err);
23
+ }
24
+ }
25
+ // ---------- 2. PR back-comment ----------
26
+ async function backCommentOnMergedPr(ctx, opts) {
27
+ if (opts.disablePrComment)
28
+ return;
29
+ const repo = ctx.repo ?? process.env.GITHUB_REPOSITORY;
30
+ if (!repo)
31
+ return;
32
+ if (!ctx.headSha)
33
+ return;
34
+ let prNumber;
35
+ try {
36
+ prNumber = findPullRequestForSha(repo, ctx.headSha);
37
+ }
38
+ catch (err) {
39
+ warn("pr-lookup", err);
40
+ return;
41
+ }
42
+ if (!prNumber)
43
+ return;
44
+ const body = `${STICKY_MARKER}\n${ctx.markdown}`;
45
+ try {
46
+ upsertStickyComment(repo, prNumber, body);
47
+ }
48
+ catch (err) {
49
+ warn("pr-comment", err);
50
+ }
51
+ }
52
+ function findPullRequestForSha(repo, sha) {
53
+ try {
54
+ const out = execFileSync("gh", [
55
+ "api",
56
+ `/repos/${repo}/commits/${sha}/pulls`,
57
+ "-H",
58
+ "Accept: application/vnd.github+json",
59
+ "--jq",
60
+ "[.[] | .number] | first",
61
+ ], { encoding: "utf8", maxBuffer: 1024 * 1024, stdio: ["ignore", "pipe", "pipe"] }).trim();
62
+ if (!out || out === "null")
63
+ return null;
64
+ const n = parseInt(out, 10);
65
+ return Number.isNaN(n) ? null : n;
66
+ }
67
+ catch {
68
+ return null;
69
+ }
70
+ }
71
+ function upsertStickyComment(repo, prNumber, body) {
72
+ const comments = JSON.parse(execFileSync("gh", [
73
+ "api",
74
+ "--paginate",
75
+ `/repos/${repo}/issues/${prNumber}/comments`,
76
+ "--jq",
77
+ "[.[] | {id, body}]",
78
+ ], { encoding: "utf8", maxBuffer: 16 * 1024 * 1024, stdio: ["ignore", "pipe", "pipe"] }));
79
+ const prior = comments.find((c) => c.body?.includes(STICKY_MARKER));
80
+ if (prior) {
81
+ execFileSync("gh", [
82
+ "api",
83
+ "-X",
84
+ "PATCH",
85
+ `/repos/${repo}/issues/comments/${prior.id}`,
86
+ "-f",
87
+ `body=${body}`,
88
+ ], { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] });
89
+ }
90
+ else {
91
+ execFileSync("gh", [
92
+ "api",
93
+ "-X",
94
+ "POST",
95
+ `/repos/${repo}/issues/${prNumber}/comments`,
96
+ "-f",
97
+ `body=${body}`,
98
+ ], { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] });
99
+ }
100
+ }
101
+ // ---------- 3. Slack ----------
102
+ async function postToSlack(ctx, opts) {
103
+ const url = opts.slackWebhook ?? process.env.CLAUDIA_SLACK_WEBHOOK;
104
+ if (!url)
105
+ return;
106
+ try {
107
+ const payload = {
108
+ text: ctx.markdown,
109
+ };
110
+ const res = await fetch(url, {
111
+ method: "POST",
112
+ headers: { "Content-Type": "application/json" },
113
+ body: JSON.stringify(payload),
114
+ });
115
+ if (!res.ok) {
116
+ warn("slack", new Error(`HTTP ${res.status}: ${await res.text().catch(() => "")}`));
117
+ }
118
+ }
119
+ catch (err) {
120
+ warn("slack", err);
121
+ }
122
+ }
123
+ function warn(label, err) {
124
+ const msg = err instanceof Error ? err.message : String(err);
125
+ process.stderr.write(`claudia: reporter[${label}] failed: ${msg}\n`);
126
+ }
127
+ //# sourceMappingURL=reporters.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reporters.js","sourceRoot":"","sources":["../src/reporters.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "@pretorian-worx/runclaudia-cli",
3
+ "version": "0.12.0",
4
+ "type": "module",
5
+ "description": "Diff-aware post-deploy test agent CLI — picks a relevant Playwright subset for a diff and runs it against the deployed prod artifact, with reporting to GitHub Actions, the merged PR, and Slack.",
6
+ "keywords": [
7
+ "ci",
8
+ "testing",
9
+ "playwright",
10
+ "post-deploy",
11
+ "diff",
12
+ "qa",
13
+ "claude",
14
+ "anthropic"
15
+ ],
16
+ "license": "MIT",
17
+ "author": "Paul Schneider",
18
+ "homepage": "https://github.com/pretorian-worx/runclaudia#readme",
19
+ "bugs": {
20
+ "url": "https://github.com/pretorian-worx/runclaudia/issues"
21
+ },
22
+ "repository": {
23
+ "type": "git",
24
+ "url": "git+https://github.com/pretorian-worx/runclaudia.git",
25
+ "directory": "packages/cli"
26
+ },
27
+ "bin": {
28
+ "claudia": "./dist/index.js"
29
+ },
30
+ "main": "./dist/index.js",
31
+ "files": [
32
+ "dist",
33
+ "README.md",
34
+ "LICENSE"
35
+ ],
36
+ "publishConfig": {
37
+ "access": "public"
38
+ },
39
+ "dependencies": {
40
+ "citty": "^0.1.6",
41
+ "@pretorian-worx/runclaudia-core": "^0.12.0"
42
+ },
43
+ "devDependencies": {
44
+ "@types/node": "^22.0.0",
45
+ "typescript": "^5.6.0",
46
+ "vitest": "^2.1.0"
47
+ },
48
+ "scripts": {
49
+ "build": "tsc -p tsconfig.json && chmod +x dist/index.js",
50
+ "start": "node ./dist/index.js",
51
+ "test": "vitest run",
52
+ "typecheck": "tsc -p tsconfig.json --noEmit"
53
+ }
54
+ }