@riddledc/riddle-proof 0.8.37 → 0.8.39
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/README.md +21 -0
- package/dist/chunk-6KYXX4OE.js +209 -0
- package/dist/{chunk-F4HKK2YH.js → chunk-MVJBPCZ4.js} +137 -5
- package/dist/cli/index.js +3 -2
- package/dist/cli.cjs +331 -0
- package/dist/cli.js +3 -2
- package/dist/index.cjs +210 -0
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +26 -18
- package/dist/pr-comment.cjs +235 -0
- package/dist/pr-comment.d.cts +41 -0
- package/dist/pr-comment.d.ts +41 -0
- package/dist/pr-comment.js +11 -0
- package/package.json +7 -2
package/README.md
CHANGED
|
@@ -968,6 +968,27 @@ way to a ready PR after proof and CI; `leave_draft: true` is only an explicit
|
|
|
968
968
|
debug or user-request escape hatch. The notification adapter is where a host
|
|
969
969
|
updates Discord, OpenClaw, GitHub, or another integration.
|
|
970
970
|
|
|
971
|
+
## PR Proof Comments
|
|
972
|
+
|
|
973
|
+
Use `pr-comment` when a project already has a PR and a Riddle Proof output
|
|
974
|
+
directory, but is not using the full ship loop. It reads
|
|
975
|
+
`riddle-run-response.json` and `result.json`, builds a managed GitHub comment,
|
|
976
|
+
embeds the primary hosted screenshot when available, links structured artifacts,
|
|
977
|
+
summarizes check counts, and updates the existing Riddle Proof comment on
|
|
978
|
+
reruns.
|
|
979
|
+
|
|
980
|
+
```sh
|
|
981
|
+
riddle-proof-loop pr-comment \
|
|
982
|
+
--proof-dir test-results/riddle-proof-docs \
|
|
983
|
+
--pr 228 \
|
|
984
|
+
--repo davisdiehl/riddle-site
|
|
985
|
+
```
|
|
986
|
+
|
|
987
|
+
Use `--dry-run` to print the exact Markdown without touching GitHub, or
|
|
988
|
+
`--body-file proof-comment.md` to save the generated body for another tool. The
|
|
989
|
+
markdown builder is also exported from `@riddledc/riddle-proof/pr-comment` for
|
|
990
|
+
host integrations that want to post comments themselves.
|
|
991
|
+
|
|
971
992
|
## Runtime Scratch Space
|
|
972
993
|
|
|
973
994
|
The packaged proof-run setup uses isolated git worktrees for before and after
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
// src/pr-comment.ts
|
|
2
|
+
var RIDDLE_PROOF_PR_COMMENT_MARKER = "<!-- riddle-proof:pr-comment:v1 -->";
|
|
3
|
+
function asRecord(value) {
|
|
4
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
5
|
+
}
|
|
6
|
+
function asArray(value) {
|
|
7
|
+
return Array.isArray(value) ? value : [];
|
|
8
|
+
}
|
|
9
|
+
function stringValue(value) {
|
|
10
|
+
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
11
|
+
}
|
|
12
|
+
function numberValue(value) {
|
|
13
|
+
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
14
|
+
}
|
|
15
|
+
function booleanValue(value) {
|
|
16
|
+
return typeof value === "boolean" ? value : void 0;
|
|
17
|
+
}
|
|
18
|
+
function artifactKind(name, url) {
|
|
19
|
+
const target = `${name} ${url}`.toLowerCase();
|
|
20
|
+
if (/\.(png|jpe?g|gif|webp|avif|svg)(\?|#|$)/.test(target)) return "image";
|
|
21
|
+
if (/\.(json|har|txt|md|html|log)(\?|#|$)/.test(target)) return "data";
|
|
22
|
+
return "artifact";
|
|
23
|
+
}
|
|
24
|
+
function artifactDisplayName(value, fallback) {
|
|
25
|
+
const raw = stringValue(value);
|
|
26
|
+
if (raw) return raw;
|
|
27
|
+
return fallback;
|
|
28
|
+
}
|
|
29
|
+
function collectArtifacts(runResponse) {
|
|
30
|
+
const proofResult = asRecord(runResponse.proofResult);
|
|
31
|
+
const outputs = asArray(proofResult.outputs);
|
|
32
|
+
const artifacts = [];
|
|
33
|
+
const seen = /* @__PURE__ */ new Set();
|
|
34
|
+
for (const [index, item] of outputs.entries()) {
|
|
35
|
+
const artifact = asRecord(item);
|
|
36
|
+
const url = stringValue(artifact.url);
|
|
37
|
+
if (!url || seen.has(url)) continue;
|
|
38
|
+
seen.add(url);
|
|
39
|
+
const name = artifactDisplayName(artifact.name, `artifact-${index + 1}`);
|
|
40
|
+
artifacts.push({
|
|
41
|
+
name,
|
|
42
|
+
url,
|
|
43
|
+
kind: artifactKind(name, url),
|
|
44
|
+
size_bytes: numberValue(artifact.size)
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
return artifacts;
|
|
48
|
+
}
|
|
49
|
+
function pageSummaries(result) {
|
|
50
|
+
const pages = [];
|
|
51
|
+
for (const page of asArray(result.pages)) {
|
|
52
|
+
const record = asRecord(page);
|
|
53
|
+
const route = stringValue(record.route) || stringValue(record.url) || "page";
|
|
54
|
+
const checks = asRecord(record.checks);
|
|
55
|
+
let passed = 0;
|
|
56
|
+
let failed = 0;
|
|
57
|
+
for (const value of Object.values(checks)) {
|
|
58
|
+
if (value === true) passed += 1;
|
|
59
|
+
if (value === false) failed += 1;
|
|
60
|
+
}
|
|
61
|
+
pages.push({ route, passed, failed });
|
|
62
|
+
}
|
|
63
|
+
return pages;
|
|
64
|
+
}
|
|
65
|
+
function summarizeExplicitChecks(value) {
|
|
66
|
+
let passed = 0;
|
|
67
|
+
let failed = 0;
|
|
68
|
+
const visit = (current, inChecks = false) => {
|
|
69
|
+
if (current === true && inChecks) {
|
|
70
|
+
passed += 1;
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
if (current === false && inChecks) {
|
|
74
|
+
failed += 1;
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
if (Array.isArray(current)) {
|
|
78
|
+
for (const item of current) visit(item, inChecks);
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
if (current && typeof current === "object") {
|
|
82
|
+
for (const [key, item] of Object.entries(current)) {
|
|
83
|
+
visit(item, inChecks || key === "checks");
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
visit(value);
|
|
88
|
+
return { passed, failed };
|
|
89
|
+
}
|
|
90
|
+
function selectPrimaryImage(artifacts) {
|
|
91
|
+
const images = artifacts.filter((artifact) => artifact.kind === "image");
|
|
92
|
+
return images.find((artifact) => /after|proof|screenshot/i.test(artifact.name)) || images[0];
|
|
93
|
+
}
|
|
94
|
+
function summarizeRiddleProofPrComment(input) {
|
|
95
|
+
const runResponse = asRecord(input.runResponse);
|
|
96
|
+
const result = asRecord(input.result);
|
|
97
|
+
const proofResult = asRecord(runResponse.proofResult);
|
|
98
|
+
const preview = asRecord(runResponse.preview);
|
|
99
|
+
const artifacts = collectArtifacts(runResponse);
|
|
100
|
+
const pages = pageSummaries(result);
|
|
101
|
+
const checkSource = { ...result };
|
|
102
|
+
delete checkSource.ok;
|
|
103
|
+
const nestedChecks = summarizeExplicitChecks(checkSource);
|
|
104
|
+
const ok = booleanValue(result.ok) ?? booleanValue(runResponse.ok) ?? null;
|
|
105
|
+
return {
|
|
106
|
+
ok,
|
|
107
|
+
status: stringValue(proofResult.status),
|
|
108
|
+
job_id: stringValue(proofResult.job_id),
|
|
109
|
+
duration_ms: numberValue(proofResult.duration_ms),
|
|
110
|
+
proof_url: stringValue(runResponse.proofUrl),
|
|
111
|
+
preview_id: stringValue(preview.id),
|
|
112
|
+
preview_url: stringValue(preview.preview_url) || stringValue(preview.url),
|
|
113
|
+
preview_publish_recovered: booleanValue(preview.publish_recovered),
|
|
114
|
+
preview_publish_error: stringValue(preview.publish_error),
|
|
115
|
+
passed_checks: nestedChecks.passed,
|
|
116
|
+
failed_checks: nestedChecks.failed,
|
|
117
|
+
pages,
|
|
118
|
+
artifacts,
|
|
119
|
+
primary_image: selectPrimaryImage(artifacts)
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
function formatDuration(ms) {
|
|
123
|
+
if (typeof ms !== "number" || !Number.isFinite(ms)) return "";
|
|
124
|
+
const seconds = Math.max(0, Math.round(ms / 1e3));
|
|
125
|
+
const minutes = Math.floor(seconds / 60);
|
|
126
|
+
const remainder = seconds % 60;
|
|
127
|
+
return minutes > 0 ? `${minutes}m${String(remainder).padStart(2, "0")}s` : `${seconds}s`;
|
|
128
|
+
}
|
|
129
|
+
function markdownLink(label, url) {
|
|
130
|
+
return `[${label.replace(/\]/g, "\\]")}](${url})`;
|
|
131
|
+
}
|
|
132
|
+
function resultLabel(summary) {
|
|
133
|
+
if (summary.ok === true) return "passed";
|
|
134
|
+
if (summary.ok === false) return "failed";
|
|
135
|
+
return summary.status || "recorded";
|
|
136
|
+
}
|
|
137
|
+
function artifactRank(artifact) {
|
|
138
|
+
const name = artifact.name.toLowerCase();
|
|
139
|
+
if (name === "proof.json") return 0;
|
|
140
|
+
if (name === "result.json") return 1;
|
|
141
|
+
if (name.includes("proof") && name.endsWith(".json") && !name.includes("layout")) return 2;
|
|
142
|
+
if (name === "console.json") return 3;
|
|
143
|
+
if (artifact.kind === "data") return 10;
|
|
144
|
+
if (artifact.kind === "image") return 20;
|
|
145
|
+
return 30;
|
|
146
|
+
}
|
|
147
|
+
function buildRiddleProofPrCommentMarkdown(input) {
|
|
148
|
+
const summary = summarizeRiddleProofPrComment(input);
|
|
149
|
+
const title = input.title?.trim() || "Riddle Proof Evidence";
|
|
150
|
+
const lines = [
|
|
151
|
+
RIDDLE_PROOF_PR_COMMENT_MARKER,
|
|
152
|
+
`## ${title}`,
|
|
153
|
+
"",
|
|
154
|
+
`**Result:** ${resultLabel(summary)}`
|
|
155
|
+
];
|
|
156
|
+
if (input.goal?.trim()) lines.push(`**Goal:** ${input.goal.trim()}`);
|
|
157
|
+
if (input.successCriteria?.trim()) lines.push(`**Success criteria:** ${input.successCriteria.trim()}`);
|
|
158
|
+
if (summary.status) lines.push(`**Riddle job status:** ${summary.status}`);
|
|
159
|
+
if (summary.job_id) lines.push(`**Riddle job:** \`${summary.job_id}\``);
|
|
160
|
+
if (summary.duration_ms) lines.push(`**Duration:** ${formatDuration(summary.duration_ms)}`);
|
|
161
|
+
if (summary.proof_url) lines.push(`**Proof URL:** ${markdownLink(summary.proof_url, summary.proof_url)}`);
|
|
162
|
+
if (summary.preview_id || summary.preview_url) {
|
|
163
|
+
const previewLabel = summary.preview_id ? `\`${summary.preview_id}\`` : "preview";
|
|
164
|
+
lines.push(`**Preview:** ${summary.preview_url ? markdownLink(previewLabel, summary.preview_url) : previewLabel}`);
|
|
165
|
+
}
|
|
166
|
+
if (summary.preview_publish_recovered) {
|
|
167
|
+
const detail = summary.preview_publish_error ? `: ${summary.preview_publish_error}` : "";
|
|
168
|
+
lines.push(`**Preview publish recovery:** recovered after publish error${detail}`);
|
|
169
|
+
}
|
|
170
|
+
lines.push(`**Checks:** ${summary.passed_checks} passed / ${summary.failed_checks} failed`);
|
|
171
|
+
lines.push("");
|
|
172
|
+
if (summary.primary_image) {
|
|
173
|
+
lines.push("### Screenshot");
|
|
174
|
+
lines.push(``);
|
|
175
|
+
lines.push("");
|
|
176
|
+
}
|
|
177
|
+
if (summary.pages.length) {
|
|
178
|
+
lines.push("### Page Checks");
|
|
179
|
+
for (const page of summary.pages.slice(0, 12)) {
|
|
180
|
+
lines.push(`- \`${page.route}\`: ${page.passed} passed / ${page.failed} failed`);
|
|
181
|
+
}
|
|
182
|
+
if (summary.pages.length > 12) lines.push(`- ${summary.pages.length - 12} more page(s) omitted`);
|
|
183
|
+
lines.push("");
|
|
184
|
+
}
|
|
185
|
+
const linkedArtifacts = summary.artifacts.filter((artifact) => artifact.url !== summary.primary_image?.url).sort((left, right) => artifactRank(left) - artifactRank(right) || left.name.localeCompare(right.name)).slice(0, 20);
|
|
186
|
+
if (linkedArtifacts.length) {
|
|
187
|
+
lines.push("### Artifacts");
|
|
188
|
+
for (const artifact of linkedArtifacts) {
|
|
189
|
+
lines.push(`- ${markdownLink(artifact.name, artifact.url)}`);
|
|
190
|
+
}
|
|
191
|
+
if (summary.artifacts.length - (summary.primary_image ? 1 : 0) > linkedArtifacts.length) {
|
|
192
|
+
lines.push(`- ${summary.artifacts.length - (summary.primary_image ? 1 : 0) - linkedArtifacts.length} more artifact(s) omitted`);
|
|
193
|
+
}
|
|
194
|
+
lines.push("");
|
|
195
|
+
}
|
|
196
|
+
if (input.source?.trim()) {
|
|
197
|
+
lines.push(`_Source: ${input.source.trim()}_`);
|
|
198
|
+
} else {
|
|
199
|
+
lines.push("_Updated by `riddle-proof-loop pr-comment`._");
|
|
200
|
+
}
|
|
201
|
+
return `${lines.join("\n").trim()}
|
|
202
|
+
`;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
export {
|
|
206
|
+
RIDDLE_PROOF_PR_COMMENT_MARKER,
|
|
207
|
+
summarizeRiddleProofPrComment,
|
|
208
|
+
buildRiddleProofPrCommentMarkdown
|
|
209
|
+
};
|
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createRiddleApiClient,
|
|
3
|
+
isTerminalRiddleJobStatus,
|
|
4
|
+
parseRiddleViewport
|
|
5
|
+
} from "./chunk-DI2XNGEZ.js";
|
|
6
|
+
import {
|
|
7
|
+
RIDDLE_PROOF_PR_COMMENT_MARKER,
|
|
8
|
+
buildRiddleProofPrCommentMarkdown,
|
|
9
|
+
summarizeRiddleProofPrComment
|
|
10
|
+
} from "./chunk-6KYXX4OE.js";
|
|
1
11
|
import {
|
|
2
12
|
RIDDLE_PROOF_PROFILE_EVIDENCE_VERSION,
|
|
3
13
|
assessRiddleProofProfileEvidence,
|
|
@@ -13,11 +23,6 @@ import {
|
|
|
13
23
|
resolveRiddleProofProfileTargetUrl,
|
|
14
24
|
resolveRiddleProofProfileTimeoutSec
|
|
15
25
|
} from "./chunk-Z2LCVROU.js";
|
|
16
|
-
import {
|
|
17
|
-
createRiddleApiClient,
|
|
18
|
-
isTerminalRiddleJobStatus,
|
|
19
|
-
parseRiddleViewport
|
|
20
|
-
} from "./chunk-DI2XNGEZ.js";
|
|
21
26
|
import {
|
|
22
27
|
createDisabledRiddleProofAgentAdapter,
|
|
23
28
|
readRiddleProofRunStatus,
|
|
@@ -56,11 +61,14 @@ var KNOWN_CLI_OPTIONS = /* @__PURE__ */ new Set([
|
|
|
56
61
|
"codexSandbox",
|
|
57
62
|
"codexTimeoutMs",
|
|
58
63
|
"command",
|
|
64
|
+
"commentMode",
|
|
59
65
|
"continueWithStage",
|
|
60
66
|
"createdAt",
|
|
61
67
|
"decision",
|
|
62
68
|
"defaultReviewer",
|
|
63
69
|
"defaultShipMode",
|
|
70
|
+
"bodyFile",
|
|
71
|
+
"dryRun",
|
|
64
72
|
"exclude",
|
|
65
73
|
"format",
|
|
66
74
|
"framework",
|
|
@@ -88,20 +96,25 @@ var KNOWN_CLI_OPTIONS = /* @__PURE__ */ new Set([
|
|
|
88
96
|
"pack",
|
|
89
97
|
"packFile",
|
|
90
98
|
"profile",
|
|
99
|
+
"proofDir",
|
|
100
|
+
"pr",
|
|
91
101
|
"progressEveryMs",
|
|
92
102
|
"quiet",
|
|
93
103
|
"readinessPath",
|
|
94
104
|
"readinessTimeout",
|
|
95
105
|
"reasonsJson",
|
|
106
|
+
"repo",
|
|
96
107
|
"requestJson",
|
|
97
108
|
"requiredJson",
|
|
98
109
|
"responseJson",
|
|
99
110
|
"resultFormat",
|
|
111
|
+
"resultJson",
|
|
100
112
|
"resultsDir",
|
|
101
113
|
"riddleEngineModuleUrl",
|
|
102
114
|
"riddleProofDir",
|
|
103
115
|
"route",
|
|
104
116
|
"runDir",
|
|
117
|
+
"runResponse",
|
|
105
118
|
"runner",
|
|
106
119
|
"scriptFile",
|
|
107
120
|
"sourceKind",
|
|
@@ -112,8 +125,10 @@ var KNOWN_CLI_OPTIONS = /* @__PURE__ */ new Set([
|
|
|
112
125
|
"submitRetries",
|
|
113
126
|
"submitTimeoutMs",
|
|
114
127
|
"summary",
|
|
128
|
+
"successCriteria",
|
|
115
129
|
"sync",
|
|
116
130
|
"timeout",
|
|
131
|
+
"title",
|
|
117
132
|
"url",
|
|
118
133
|
"unsubmittedJobRetries",
|
|
119
134
|
"unsubmittedJobTimeoutMs",
|
|
@@ -138,6 +153,7 @@ function usage() {
|
|
|
138
153
|
" riddle-proof-loop run-profile aggregate --profile <file|json|-> --url <base-url> [--base-url <base-url>] --input-dir <dir>|--inputs <path[,path...]> [--output <dir>|--output-dir <dir>] [--result-format json|compact-json|summary|none; default json]",
|
|
139
154
|
" riddle-proof-loop run-profile recover --profile <file|json|-> --url <base-url> [--base-url <base-url>] --job <job-id> [--viewport-name <name[,name...]>] [--output <dir>|--output-dir <dir>] [--result-format json|compact-json|summary|none; default json]",
|
|
140
155
|
" riddle-proof-loop regression-pack run [--pack oc-flow-regression|--pack-file <file>] [--local-core true|false; default true] [--hosted-riddle true|false; default false] [--format json|markdown|compact-json; default json] [--output <dir>|--output-dir <dir>]",
|
|
156
|
+
" riddle-proof-loop pr-comment --proof-dir <dir>|--run-response <file> [--result-json <file>] --pr <number|url> [--repo owner/name] [--dry-run] [--body-file <file>] [--comment-mode update|append]",
|
|
141
157
|
" riddle-proof-loop profile-body-assertions --artifact <file|url|-> --candidates-json <file|json|-> [--required-json <file|json|->] [--format json|body-contains]",
|
|
142
158
|
" riddle-proof-loop profile-http-status-preflight --profile <file|json|-> --url <base-url> [--format json|summary]",
|
|
143
159
|
" riddle-proof-loop riddle-preview-deploy <build-dir> <label> [--framework spa|static] [--quiet]",
|
|
@@ -946,6 +962,81 @@ function riddlePreviewProgressLine(snapshot) {
|
|
|
946
962
|
const messagePart = snapshot.message ? ` ${snapshot.message}` : "";
|
|
947
963
|
return `[riddle-preview] ${snapshot.stage}${idPart}${statusPart}${attemptPart} elapsed=${formatPollDuration(snapshot.elapsed_ms)} label=${snapshot.label} framework=${snapshot.framework}${filePart}${totalPart}${archivePart}${previewPart}${recoveryPart}${messagePart}`;
|
|
948
964
|
}
|
|
965
|
+
function readJsonFileIfExists(filePath) {
|
|
966
|
+
if (!filePath || !existsSync(filePath)) return void 0;
|
|
967
|
+
return readJsonValue(filePath, filePath);
|
|
968
|
+
}
|
|
969
|
+
function defaultProofDirJsonPath(proofDir, filename) {
|
|
970
|
+
return proofDir ? path.join(proofDir, filename) : void 0;
|
|
971
|
+
}
|
|
972
|
+
function prNumberFromValue(value) {
|
|
973
|
+
const text = value?.trim();
|
|
974
|
+
if (!text) return "";
|
|
975
|
+
const match = text.match(/\/pull\/(\d+)(?:\/|$)/) || text.match(/^#?(\d+)$/);
|
|
976
|
+
return match ? match[1] : text;
|
|
977
|
+
}
|
|
978
|
+
function ghJson(args, input) {
|
|
979
|
+
const result = spawnSync("gh", args, {
|
|
980
|
+
input: typeof input === "undefined" ? void 0 : `${JSON.stringify(input)}
|
|
981
|
+
`,
|
|
982
|
+
encoding: "utf-8",
|
|
983
|
+
timeout: 9e4
|
|
984
|
+
});
|
|
985
|
+
if (result.error) throw result.error;
|
|
986
|
+
if (result.status !== 0) {
|
|
987
|
+
const detail = (result.stderr || result.stdout || "").trim();
|
|
988
|
+
throw new Error(`gh ${args.join(" ")} failed${detail ? `: ${detail}` : ""}`);
|
|
989
|
+
}
|
|
990
|
+
const stdout = (result.stdout || "").trim();
|
|
991
|
+
return stdout ? JSON.parse(stdout) : {};
|
|
992
|
+
}
|
|
993
|
+
function resolveGhRepoName(repoOption) {
|
|
994
|
+
if (repoOption?.trim()) return repoOption.trim();
|
|
995
|
+
const result = spawnSync("gh", ["repo", "view", "--json", "nameWithOwner", "--jq", ".nameWithOwner"], {
|
|
996
|
+
encoding: "utf-8",
|
|
997
|
+
timeout: 3e4
|
|
998
|
+
});
|
|
999
|
+
if (result.error) throw result.error;
|
|
1000
|
+
if (result.status !== 0 || !result.stdout.trim()) {
|
|
1001
|
+
const detail = (result.stderr || result.stdout || "").trim();
|
|
1002
|
+
throw new Error(`Could not resolve GitHub repository. Pass --repo owner/name.${detail ? ` gh said: ${detail}` : ""}`);
|
|
1003
|
+
}
|
|
1004
|
+
return result.stdout.trim();
|
|
1005
|
+
}
|
|
1006
|
+
function findManagedPrComment(repo, prNumber) {
|
|
1007
|
+
const comments = ghJson(["api", `repos/${repo}/issues/${prNumber}/comments`, "--paginate"]);
|
|
1008
|
+
return comments.find((comment) => typeof comment.body === "string" && comment.body.includes(RIDDLE_PROOF_PR_COMMENT_MARKER));
|
|
1009
|
+
}
|
|
1010
|
+
function upsertPrComment(input) {
|
|
1011
|
+
const payload = { body: input.body };
|
|
1012
|
+
if (input.mode !== "append") {
|
|
1013
|
+
const existing = findManagedPrComment(input.repo, input.prNumber);
|
|
1014
|
+
if (existing?.id) {
|
|
1015
|
+
return {
|
|
1016
|
+
action: "updated",
|
|
1017
|
+
comment: ghJson([
|
|
1018
|
+
"api",
|
|
1019
|
+
`repos/${input.repo}/issues/comments/${existing.id}`,
|
|
1020
|
+
"-X",
|
|
1021
|
+
"PATCH",
|
|
1022
|
+
"--input",
|
|
1023
|
+
"-"
|
|
1024
|
+
], payload)
|
|
1025
|
+
};
|
|
1026
|
+
}
|
|
1027
|
+
}
|
|
1028
|
+
return {
|
|
1029
|
+
action: "created",
|
|
1030
|
+
comment: ghJson([
|
|
1031
|
+
"api",
|
|
1032
|
+
`repos/${input.repo}/issues/${input.prNumber}/comments`,
|
|
1033
|
+
"-X",
|
|
1034
|
+
"POST",
|
|
1035
|
+
"--input",
|
|
1036
|
+
"-"
|
|
1037
|
+
], payload)
|
|
1038
|
+
};
|
|
1039
|
+
}
|
|
949
1040
|
function readJsonValue(value, label) {
|
|
950
1041
|
if (!value) throw new Error(`${label} is required.`);
|
|
951
1042
|
const raw = value === "-" ? readStdin() : existsSync(value) ? readFileSync(value, "utf-8") : value;
|
|
@@ -4578,6 +4669,47 @@ async function main() {
|
|
|
4578
4669
|
process.exitCode = result.ok ? 0 : 1;
|
|
4579
4670
|
return;
|
|
4580
4671
|
}
|
|
4672
|
+
if (command === "pr-comment") {
|
|
4673
|
+
const proofDir = optionString(options, "proofDir") || optionString(options, "outputDir") || positional[1];
|
|
4674
|
+
const runResponsePath = optionString(options, "runResponse") || defaultProofDirJsonPath(proofDir, "riddle-run-response.json");
|
|
4675
|
+
const resultJsonPath = optionString(options, "resultJson") || defaultProofDirJsonPath(proofDir, "result.json");
|
|
4676
|
+
const runResponse = readJsonFileIfExists(runResponsePath);
|
|
4677
|
+
const result = readJsonFileIfExists(resultJsonPath);
|
|
4678
|
+
if (!runResponse && !result) {
|
|
4679
|
+
throw new Error("pr-comment requires --proof-dir with riddle-run-response.json/result.json or explicit --run-response/--result-json.");
|
|
4680
|
+
}
|
|
4681
|
+
const body = buildRiddleProofPrCommentMarkdown({
|
|
4682
|
+
title: optionString(options, "title"),
|
|
4683
|
+
goal: optionString(options, "summary"),
|
|
4684
|
+
successCriteria: optionString(options, "successCriteria"),
|
|
4685
|
+
runResponse,
|
|
4686
|
+
result
|
|
4687
|
+
});
|
|
4688
|
+
const bodyFile = optionString(options, "bodyFile");
|
|
4689
|
+
if (bodyFile) writeFileSync(bodyFile, body);
|
|
4690
|
+
if (optionBoolean(options, "dryRun")) {
|
|
4691
|
+
process.stdout.write(body);
|
|
4692
|
+
return;
|
|
4693
|
+
}
|
|
4694
|
+
const prNumber = prNumberFromValue(optionString(options, "pr"));
|
|
4695
|
+
if (!prNumber) throw new Error("pr-comment requires --pr <number|url> unless --dry-run is used.");
|
|
4696
|
+
const commentMode = optionString(options, "commentMode") || "update";
|
|
4697
|
+
if (!["update", "append"].includes(commentMode)) throw new Error("--comment-mode must be update or append.");
|
|
4698
|
+
const repo = resolveGhRepoName(optionString(options, "repo"));
|
|
4699
|
+
const resultPayload = upsertPrComment({ repo, prNumber, body, mode: commentMode });
|
|
4700
|
+
const comment = resultPayload.comment;
|
|
4701
|
+
process.stdout.write(`${JSON.stringify({
|
|
4702
|
+
ok: true,
|
|
4703
|
+
action: resultPayload.action,
|
|
4704
|
+
repo,
|
|
4705
|
+
pr: prNumber,
|
|
4706
|
+
comment_url: cliString(comment.html_url) || null,
|
|
4707
|
+
summary: summarizeRiddleProofPrComment({ runResponse, result }),
|
|
4708
|
+
body_file: bodyFile || null
|
|
4709
|
+
}, null, 2)}
|
|
4710
|
+
`);
|
|
4711
|
+
return;
|
|
4712
|
+
}
|
|
4581
4713
|
if (command === "profile-http-status-preflight") {
|
|
4582
4714
|
const profile = normalizeProfileForCli(options);
|
|
4583
4715
|
const result = await preflightRiddleProofProfileHttpStatusChecks(profile);
|
package/dist/cli/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import "../chunk-
|
|
2
|
-
import "../chunk-Z2LCVROU.js";
|
|
1
|
+
import "../chunk-MVJBPCZ4.js";
|
|
3
2
|
import "../chunk-DI2XNGEZ.js";
|
|
3
|
+
import "../chunk-6KYXX4OE.js";
|
|
4
|
+
import "../chunk-Z2LCVROU.js";
|
|
4
5
|
import "../chunk-ZREWMTFA.js";
|
|
5
6
|
import "../chunk-ZQWVXQKJ.js";
|
|
6
7
|
import "../chunk-RDPG554T.js";
|