@agent-native/recap-cli 0.5.66 → 0.5.68-nightly-20261009011246
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/dist/pr-visual-recap-workflow.js +1 -1
- package/dist/recap.d.ts +7 -1
- package/dist/recap.d.ts.map +1 -1
- package/dist/recap.js +130 -11
- package/dist/recap.js.map +1 -1
- package/dist/workflows/pr-visual-recap.yml +270 -6
- package/package.json +1 -1
|
@@ -790,12 +790,13 @@ jobs:
|
|
|
790
790
|
# preserving path-prefixed self-hosted mounts.
|
|
791
791
|
if [ -z "$URL_REASON" ]; then
|
|
792
792
|
URL_RESULT=$(PLAN_URL="$PLAN_URL" node <<'NODE'
|
|
793
|
+
void (() => {
|
|
793
794
|
const emit = (value) => process.stdout.write(JSON.stringify(value));
|
|
794
795
|
try {
|
|
795
796
|
const raw = process.env.PLAN_URL || "";
|
|
796
797
|
if (!raw) {
|
|
797
798
|
emit({ url: "", reason: "recap-url.txt was empty" });
|
|
798
|
-
|
|
799
|
+
return;
|
|
799
800
|
}
|
|
800
801
|
const trusted = new URL(process.env.PLAN_RECAP_APP_URL || "https://plan.agent-native.com");
|
|
801
802
|
const parsed = /^https?:\/\//i.test(raw)
|
|
@@ -803,7 +804,7 @@ jobs:
|
|
|
803
804
|
: new URL(raw, trusted);
|
|
804
805
|
if (parsed.origin !== trusted.origin) {
|
|
805
806
|
emit({ url: "", reason: `recap-url.txt points at ${parsed.origin}, expected ${trusted.origin}` });
|
|
806
|
-
|
|
807
|
+
return;
|
|
807
808
|
}
|
|
808
809
|
|
|
809
810
|
const base = trusted.pathname.replace(/\/$/, "");
|
|
@@ -816,13 +817,14 @@ jobs:
|
|
|
816
817
|
const match = path.match(/^\/(?:plans|recaps)\/([A-Za-z0-9_-]+)\/?$/);
|
|
817
818
|
if (match) {
|
|
818
819
|
emit({ url: `${trusted.origin}${base}/recaps/${match[1]}`, reason: "" });
|
|
819
|
-
|
|
820
|
+
return;
|
|
820
821
|
}
|
|
821
822
|
}
|
|
822
823
|
emit({ url: "", reason: "recap-url.txt did not contain a valid /plans/<id> or /recaps/<id> URL for the configured plan app" });
|
|
823
824
|
} catch {
|
|
824
825
|
emit({ url: "", reason: "recap-url.txt was not a valid URL or recap path" });
|
|
825
826
|
}
|
|
827
|
+
})();
|
|
826
828
|
NODE
|
|
827
829
|
)
|
|
828
830
|
CANONICAL_URL=$(node -e 'try{process.stdout.write(JSON.parse(process.argv[1]).url||"")}catch{process.stdout.write("")}' "$URL_RESULT")
|
|
@@ -926,14 +928,130 @@ jobs:
|
|
|
926
928
|
path: ~/.cache/ms-playwright
|
|
927
929
|
key: playwright-1-${{ runner.os }}
|
|
928
930
|
|
|
931
|
+
- name: Verify published recap readback
|
|
932
|
+
id: readback
|
|
933
|
+
if: always() && !cancelled() && steps.url.outputs.ok == 'true'
|
|
934
|
+
env:
|
|
935
|
+
PLAN_URL: ${{ steps.url.outputs.plan_url }}
|
|
936
|
+
run: |
|
|
937
|
+
set -uo pipefail
|
|
938
|
+
READBACK_JSON=$(node <<'NODE'
|
|
939
|
+
void (async () => {
|
|
940
|
+
const emit = (value) => process.stdout.write(JSON.stringify(value));
|
|
941
|
+
let requestAttempts = 0;
|
|
942
|
+
try {
|
|
943
|
+
const base = new URL(process.env.PLAN_RECAP_APP_URL || "https://plan.agent-native.com");
|
|
944
|
+
const recap = new URL(process.env.PLAN_URL || "");
|
|
945
|
+
if (recap.origin !== base.origin) {
|
|
946
|
+
emit({ ok: false, reason: "published recap URL origin does not match the configured Plan app" });
|
|
947
|
+
return;
|
|
948
|
+
}
|
|
949
|
+
const basePath = base.pathname.replace(/\/+$/, "");
|
|
950
|
+
let recapPath = recap.pathname;
|
|
951
|
+
if (basePath && recapPath.startsWith(`${basePath}/`)) recapPath = recapPath.slice(basePath.length);
|
|
952
|
+
const match = recapPath.match(/^\/(?:plans|recaps)\/([A-Za-z0-9_-]+)\/?$/);
|
|
953
|
+
if (!match) {
|
|
954
|
+
emit({ ok: false, reason: "published recap URL does not contain a valid Plan ID" });
|
|
955
|
+
return;
|
|
956
|
+
}
|
|
957
|
+
const actionUrl = new URL(base.href);
|
|
958
|
+
actionUrl.pathname = `${basePath}/_agent-native/actions/get-visual-plan`;
|
|
959
|
+
actionUrl.search = "";
|
|
960
|
+
actionUrl.hash = "";
|
|
961
|
+
if (actionUrl.origin !== base.origin) {
|
|
962
|
+
emit({ ok: false, reason: "get-visual-plan URL origin does not match the configured Plan app" });
|
|
963
|
+
return;
|
|
964
|
+
}
|
|
965
|
+
actionUrl.searchParams.set("id", match[1]);
|
|
966
|
+
actionUrl.searchParams.set("includeHtml", "false");
|
|
967
|
+
actionUrl.searchParams.set("includeMdx", "false");
|
|
968
|
+
let response;
|
|
969
|
+
let payload;
|
|
970
|
+
for (requestAttempts = 1; requestAttempts <= 3; requestAttempts++) {
|
|
971
|
+
try {
|
|
972
|
+
response = await fetch(actionUrl, {
|
|
973
|
+
headers: { authorization: `Bearer ${process.env.PLAN_RECAP_TOKEN || ""}` },
|
|
974
|
+
signal: AbortSignal.timeout(15000),
|
|
975
|
+
});
|
|
976
|
+
const retryableStatus = response.status === 408 || response.status === 429 || response.status >= 500;
|
|
977
|
+
if (retryableStatus && requestAttempts < 3) {
|
|
978
|
+
await new Promise((resolve) => setTimeout(resolve, requestAttempts * 250));
|
|
979
|
+
continue;
|
|
980
|
+
}
|
|
981
|
+
if (!response.ok) break;
|
|
982
|
+
payload = await response.json();
|
|
983
|
+
break;
|
|
984
|
+
} catch (error) {
|
|
985
|
+
const retryable = error?.name === "TimeoutError" || error instanceof TypeError;
|
|
986
|
+
if (!retryable || requestAttempts === 3) throw error;
|
|
987
|
+
await new Promise((resolve) => setTimeout(resolve, requestAttempts * 250));
|
|
988
|
+
}
|
|
989
|
+
}
|
|
990
|
+
if (!response.ok) {
|
|
991
|
+
const hint = response.status === 401 || response.status === 403
|
|
992
|
+
? "the configured token cannot read this published recap"
|
|
993
|
+
: response.status === 404
|
|
994
|
+
? "the Plan read action or published recap is not available"
|
|
995
|
+
: "the Plan read action returned an error";
|
|
996
|
+
const attempts = requestAttempts > 1 ? ` after ${requestAttempts} attempts` : "";
|
|
997
|
+
emit({ ok: false, reason: `get-visual-plan returned HTTP ${response.status}${attempts}; ${hint}` });
|
|
998
|
+
return;
|
|
999
|
+
}
|
|
1000
|
+
const returnedId = payload?.plan?.id ?? payload?.planId ?? payload?.data?.plan?.id;
|
|
1001
|
+
if (returnedId !== match[1]) {
|
|
1002
|
+
emit({ ok: false, reason: "get-visual-plan returned a response without the published Plan ID" });
|
|
1003
|
+
return;
|
|
1004
|
+
}
|
|
1005
|
+
emit({ ok: true, reason: "" });
|
|
1006
|
+
} catch (error) {
|
|
1007
|
+
const attempts = requestAttempts > 1 ? ` after ${requestAttempts} attempts` : "";
|
|
1008
|
+
const reason = error?.name === "TimeoutError"
|
|
1009
|
+
? `get-visual-plan readback timed out${attempts}`
|
|
1010
|
+
: `get-visual-plan readback request failed${attempts}`;
|
|
1011
|
+
emit({ ok: false, reason });
|
|
1012
|
+
}
|
|
1013
|
+
})();
|
|
1014
|
+
NODE
|
|
1015
|
+
)
|
|
1016
|
+
READBACK_OK=$(node -e 'try{process.stdout.write(JSON.parse(process.argv[1]).ok===true?"true":"false")}catch{process.stdout.write("false")}' "$READBACK_JSON")
|
|
1017
|
+
READBACK_REASON=$(node -e 'try{process.stdout.write(JSON.parse(process.argv[1]).reason||"")}catch{process.stdout.write("invalid readback result")}' "$READBACK_JSON")
|
|
1018
|
+
if [ "$READBACK_OK" = "true" ]; then
|
|
1019
|
+
echo "[recap readback] published plan is readable"
|
|
1020
|
+
else
|
|
1021
|
+
echo "::warning::Published recap readback failed: $READBACK_REASON"
|
|
1022
|
+
fi
|
|
1023
|
+
echo "ok=$READBACK_OK" >> "$GITHUB_OUTPUT"
|
|
1024
|
+
{
|
|
1025
|
+
echo 'reason<<__RECAP_READBACK_REASON_EOF__'
|
|
1026
|
+
echo "$READBACK_REASON"
|
|
1027
|
+
echo '__RECAP_READBACK_REASON_EOF__'
|
|
1028
|
+
} >> "$GITHUB_OUTPUT"
|
|
1029
|
+
|
|
929
1030
|
- name: Screenshot + upload
|
|
930
1031
|
id: shot
|
|
931
|
-
if: steps.url.outputs.ok == 'true'
|
|
1032
|
+
if: always() && !cancelled() && steps.url.outputs.ok == 'true'
|
|
932
1033
|
continue-on-error: true
|
|
933
1034
|
env:
|
|
934
1035
|
PLAN_URL: ${{ steps.url.outputs.plan_url }}
|
|
1036
|
+
PLAN_READBACK_OK: ${{ steps.readback.outputs.ok }}
|
|
1037
|
+
PLAN_READBACK_REASON: ${{ steps.readback.outputs.reason }}
|
|
935
1038
|
run: |
|
|
936
1039
|
set -uo pipefail
|
|
1040
|
+
if [ "${PLAN_READBACK_OK:-false}" != "true" ]; then
|
|
1041
|
+
SHOT_REASON="Published recap readback failed: ${PLAN_READBACK_REASON:-the readback step did not complete.}"
|
|
1042
|
+
echo "::warning::$SHOT_REASON"
|
|
1043
|
+
echo "shot_ok=false" >> "$GITHUB_OUTPUT"
|
|
1044
|
+
echo "captured=false" >> "$GITHUB_OUTPUT"
|
|
1045
|
+
echo "image_url=" >> "$GITHUB_OUTPUT"
|
|
1046
|
+
echo "light_image_url=" >> "$GITHUB_OUTPUT"
|
|
1047
|
+
echo "dark_image_url=" >> "$GITHUB_OUTPUT"
|
|
1048
|
+
{
|
|
1049
|
+
echo 'shot_reason<<__RECAP_SHOT_REASON_EOF__'
|
|
1050
|
+
echo "$SHOT_REASON"
|
|
1051
|
+
echo '__RECAP_SHOT_REASON_EOF__'
|
|
1052
|
+
} >> "$GITHUB_OUTPUT"
|
|
1053
|
+
exit 0
|
|
1054
|
+
fi
|
|
937
1055
|
if [ -n "${RECAP_PLAYWRIGHT:-}" ] && [ -x "$RECAP_PLAYWRIGHT" ]; then
|
|
938
1056
|
"$RECAP_PLAYWRIGHT" install --with-deps chromium || true
|
|
939
1057
|
elif command -v pnpm >/dev/null 2>&1; then
|
|
@@ -1027,6 +1145,8 @@ jobs:
|
|
|
1027
1145
|
RECAP_IMAGE_URL: ${{ steps.shot.outputs.image_url }}
|
|
1028
1146
|
RECAP_LIGHT_IMAGE_URL: ${{ steps.shot.outputs.light_image_url }}
|
|
1029
1147
|
RECAP_DARK_IMAGE_URL: ${{ steps.shot.outputs.dark_image_url }}
|
|
1148
|
+
RECAP_READBACK_OK: ${{ steps.readback.outputs.ok }}
|
|
1149
|
+
RECAP_READBACK_REASON: ${{ steps.readback.outputs.reason }}
|
|
1030
1150
|
RECAP_SHOT_OK: ${{ steps.shot.outputs.shot_ok }}
|
|
1031
1151
|
RECAP_SHOT_REASON: ${{ steps.shot.outputs.shot_reason }}
|
|
1032
1152
|
SUPPRESSED: ${{ steps.scan.outputs.suppressed }}
|
|
@@ -1046,8 +1166,13 @@ jobs:
|
|
|
1046
1166
|
continue-on-error: true
|
|
1047
1167
|
env:
|
|
1048
1168
|
CHECK_RUN_ID: ${{ steps.recap_check.outputs.check_run_id }}
|
|
1049
|
-
PLAN_OK: ${{ steps.url.outputs.ok }}
|
|
1169
|
+
PLAN_OK: ${{ steps.url.outputs.ok == 'true' && steps.shot.outputs.shot_ok == 'true' }}
|
|
1170
|
+
URL_OK: ${{ steps.url.outputs.ok }}
|
|
1050
1171
|
PLAN_URL: ${{ steps.url.outputs.plan_url }}
|
|
1172
|
+
READBACK_OK: ${{ steps.readback.outputs.ok }}
|
|
1173
|
+
READBACK_REASON: ${{ steps.readback.outputs.reason }}
|
|
1174
|
+
SHOT_OK: ${{ steps.shot.outputs.shot_ok }}
|
|
1175
|
+
SHOT_REASON: ${{ steps.shot.outputs.shot_reason }}
|
|
1051
1176
|
SUPPRESSED: ${{ steps.scan.outputs.suppressed }}
|
|
1052
1177
|
SUPPRESSED_JSON: ${{ steps.scan.outputs.json }}
|
|
1053
1178
|
DIFF_HUGE: ${{ steps.diff.outputs.huge }}
|
|
@@ -1056,14 +1181,153 @@ jobs:
|
|
|
1056
1181
|
RECAP_URL_REASON: ${{ steps.route_health.outputs.reason || steps.source_status.outputs.reason || steps.url.outputs.reason }}
|
|
1057
1182
|
run: |
|
|
1058
1183
|
set -uo pipefail
|
|
1184
|
+
CLI_SHOT_REASON=""
|
|
1185
|
+
CLI_SHOT_OK="$SHOT_OK"
|
|
1186
|
+
CLI_READBACK_REASON=""
|
|
1187
|
+
CLI_FAILURE_SUMMARY="$RECAP_AGENT_SUMMARY"
|
|
1188
|
+
FAILURE_STAGE=""
|
|
1189
|
+
FAILURE_REASON=""
|
|
1190
|
+
if [ "$URL_OK" = "true" ] && [ "$READBACK_OK" != "true" ]; then
|
|
1191
|
+
FAILURE_STAGE="readback"
|
|
1192
|
+
FAILURE_REASON="$READBACK_REASON"
|
|
1193
|
+
elif [ "$URL_OK" = "true" ] && [ "$SHOT_OK" != "true" ]; then
|
|
1194
|
+
FAILURE_STAGE="screenshot"
|
|
1195
|
+
FAILURE_REASON="$SHOT_REASON"
|
|
1196
|
+
fi
|
|
1197
|
+
if [ -n "$FAILURE_STAGE" ]; then
|
|
1198
|
+
FAILURE_DIAGNOSTIC=$(FAILURE_REASON="$FAILURE_REASON" node <<'NODE'
|
|
1199
|
+
const patterns = [
|
|
1200
|
+
/\bsk-(?:proj-)?[A-Za-z0-9_-]{24,}\b/,
|
|
1201
|
+
/\b(?:sk|rk)_live_[A-Za-z0-9]{16,}\b/,
|
|
1202
|
+
/\bSG\.[A-Za-z0-9_-]{16,}\.[A-Za-z0-9_-]{16,}\b/,
|
|
1203
|
+
/\bGOCSPX-[A-Za-z0-9_-]{20,}\b/,
|
|
1204
|
+
/\bbpk-[A-Za-z0-9_-]{16,}\b/,
|
|
1205
|
+
/\bghp_[A-Za-z0-9]{20,}\b/,
|
|
1206
|
+
/\bgithub_pat_[A-Za-z0-9_]{20,}\b/,
|
|
1207
|
+
/\bxox[baprs]-[A-Za-z0-9-]{10,}\b/,
|
|
1208
|
+
/\bAKIA[0-9A-Z]{16}\b/,
|
|
1209
|
+
/\bAIza[0-9A-Za-z_-]{20,}\b/,
|
|
1210
|
+
/authorization\s*[:=]\s*['"]?bearer\s+[A-Za-z0-9._-]{20,}/i,
|
|
1211
|
+
/-----BEGIN (?:RSA |EC |OPENSSH |DSA |PGP )?PRIVATE KEY-----/,
|
|
1212
|
+
];
|
|
1213
|
+
const redact = (line) => line
|
|
1214
|
+
.replace(/Authorization\s*[:=]\s*Bearer\s+\S+/gi, "Authorization: Bearer [redacted]")
|
|
1215
|
+
.replace(/Bearer\s+\S+/gi, "Bearer [redacted]")
|
|
1216
|
+
.replace(/Authorization\s*[:=]\s*(?!Bearer\s+\[redacted\])(?:\S+\s+)?\S+/gi, "Authorization: [redacted]")
|
|
1217
|
+
.replace(/\b[A-Z0-9_]*(?:SECRET|TOKEN|PASSWORD|API_KEY|PRIVATE_KEY|ACCESS_KEY)[A-Z0-9_]*\s*=\s*[^\s]+/gi, "[redacted credential]");
|
|
1218
|
+
const text = (process.env.FAILURE_REASON || "")
|
|
1219
|
+
.replace(/\u001b\[[0-9;]*m/g, "")
|
|
1220
|
+
.split("\n")
|
|
1221
|
+
.map(redact)
|
|
1222
|
+
.map((line) => patterns.some((pattern) => pattern.test(line)) ? "[redacted sensitive line]" : line)
|
|
1223
|
+
.join(" ")
|
|
1224
|
+
.replace(/\s+/g, " ")
|
|
1225
|
+
.trim();
|
|
1226
|
+
const summary = text.length <= 400 ? text : `${text.slice(0, 399).trimEnd()}…`;
|
|
1227
|
+
process.stdout.write(summary);
|
|
1228
|
+
NODE
|
|
1229
|
+
)
|
|
1230
|
+
FAILURE_DIAGNOSTIC=${FAILURE_DIAGNOSTIC:-$FAILURE_STAGE verification failed}
|
|
1231
|
+
if [ "$FAILURE_STAGE" = "readback" ]; then
|
|
1232
|
+
CLI_READBACK_REASON="$FAILURE_DIAGNOSTIC"
|
|
1233
|
+
FAILURE_TITLE="Visual recap readback failed"
|
|
1234
|
+
FAILURE_SUMMARY="The recap was published, but the workflow could not verify it. Screenshot capture was skipped. This informational check does not block the PR."
|
|
1235
|
+
FAILURE_TEXT="[Open visual recap]($PLAN_URL) — readback failed: $FAILURE_DIAGNOSTIC. Screenshot capture was skipped. See this workflow run for details."
|
|
1236
|
+
else
|
|
1237
|
+
CLI_SHOT_REASON="$FAILURE_DIAGNOSTIC"
|
|
1238
|
+
FAILURE_TITLE="Visual recap screenshot failed"
|
|
1239
|
+
FAILURE_SUMMARY="The recap was published, but its screenshot failed: $FAILURE_DIAGNOSTIC. This informational check does not block the PR."
|
|
1240
|
+
FAILURE_TEXT="[Open visual recap]($PLAN_URL) — screenshot failed: $FAILURE_DIAGNOSTIC. See this workflow run for details."
|
|
1241
|
+
fi
|
|
1242
|
+
if gh api --method PATCH \
|
|
1243
|
+
"repos/$GITHUB_REPOSITORY/check-runs/$CHECK_RUN_ID" \
|
|
1244
|
+
-f status=completed \
|
|
1245
|
+
-f conclusion=failure \
|
|
1246
|
+
-f completed_at="$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
|
|
1247
|
+
-f details_url="$PLAN_URL" \
|
|
1248
|
+
-f "output[title]=$FAILURE_TITLE" \
|
|
1249
|
+
-f "output[summary]=$FAILURE_SUMMARY" \
|
|
1250
|
+
-f "output[text]=$FAILURE_TEXT" \
|
|
1251
|
+
> /dev/null; then
|
|
1252
|
+
exit 0
|
|
1253
|
+
fi
|
|
1254
|
+
echo "::warning::Could not set $FAILURE_STAGE failure on the Visual Recap check with gh; retrying through the workflow-owned API fallback."
|
|
1255
|
+
if node --input-type=module - "$FAILURE_STAGE" "$FAILURE_TITLE" "$FAILURE_SUMMARY" "$FAILURE_TEXT" <<'NODE'
|
|
1256
|
+
const [failureStage, failureTitle, failureSummary, failureText] = process.argv.slice(2);
|
|
1257
|
+
const token = process.env.GH_TOKEN;
|
|
1258
|
+
const repository = process.env.GITHUB_REPOSITORY;
|
|
1259
|
+
const [owner, name, ...extra] = (repository || '').split('/');
|
|
1260
|
+
const checkRunId = process.env.CHECK_RUN_ID;
|
|
1261
|
+
if (!token || !owner || !name || extra.length || !/^\d+$/.test(checkRunId || '')) {
|
|
1262
|
+
process.stderr.write('Visual Recap check fallback is missing required GitHub API context.\n');
|
|
1263
|
+
process.exit(1);
|
|
1264
|
+
}
|
|
1265
|
+
|
|
1266
|
+
const apiBase = (process.env.GITHUB_API_URL || 'https://api.github.com').replace(/\/+$/, '');
|
|
1267
|
+
const endpoint = `${apiBase}/repos/${encodeURIComponent(owner)}/${encodeURIComponent(name)}/check-runs/${checkRunId}`;
|
|
1268
|
+
const payload = {
|
|
1269
|
+
status: 'completed',
|
|
1270
|
+
conclusion: 'failure',
|
|
1271
|
+
completed_at: new Date().toISOString(),
|
|
1272
|
+
details_url: process.env.PLAN_URL,
|
|
1273
|
+
output: {
|
|
1274
|
+
title: failureTitle,
|
|
1275
|
+
summary: failureSummary,
|
|
1276
|
+
text: failureText,
|
|
1277
|
+
},
|
|
1278
|
+
};
|
|
1279
|
+
async function updateCheckRun() {
|
|
1280
|
+
const delays = [0, 500, 1500];
|
|
1281
|
+
let lastStatus;
|
|
1282
|
+
|
|
1283
|
+
for (let attempt = 0; attempt < delays.length; attempt += 1) {
|
|
1284
|
+
if (delays[attempt]) await new Promise((resolve) => setTimeout(resolve, delays[attempt]));
|
|
1285
|
+
try {
|
|
1286
|
+
const response = await fetch(endpoint, {
|
|
1287
|
+
method: 'PATCH',
|
|
1288
|
+
headers: {
|
|
1289
|
+
Accept: 'application/vnd.github+json',
|
|
1290
|
+
Authorization: `Bearer ${token}`,
|
|
1291
|
+
'Content-Type': 'application/json',
|
|
1292
|
+
},
|
|
1293
|
+
body: JSON.stringify(payload),
|
|
1294
|
+
});
|
|
1295
|
+
if (response.ok) {
|
|
1296
|
+
process.stdout.write('Visual Recap failure detail was written through the workflow-owned API fallback.\n');
|
|
1297
|
+
return true;
|
|
1298
|
+
}
|
|
1299
|
+
lastStatus = response.status;
|
|
1300
|
+
if (response.status !== 408 && response.status !== 429 && response.status < 500) break;
|
|
1301
|
+
} catch {
|
|
1302
|
+
lastStatus = 'network error';
|
|
1303
|
+
}
|
|
1304
|
+
}
|
|
1305
|
+
|
|
1306
|
+
process.stderr.write(`Visual Recap API fallback could not record the ${failureStage} failure (${lastStatus || 'unknown error'}).\n`);
|
|
1307
|
+
return false;
|
|
1308
|
+
}
|
|
1309
|
+
|
|
1310
|
+
if (await updateCheckRun()) process.exit(0);
|
|
1311
|
+
process.exit(1);
|
|
1312
|
+
NODE
|
|
1313
|
+
then
|
|
1314
|
+
exit 0
|
|
1315
|
+
fi
|
|
1316
|
+
echo "::error::Visual Recap failure details could not be written; leaving the informational check unresolved rather than replacing the stage-specific failure with a generic legacy CLI result."
|
|
1317
|
+
exit 1
|
|
1318
|
+
fi
|
|
1059
1319
|
$RECAP_CLI recap check complete \
|
|
1060
1320
|
--check-run-id "$CHECK_RUN_ID" \
|
|
1061
1321
|
--plan-ok "$PLAN_OK" \
|
|
1062
1322
|
--plan-url "$PLAN_URL" \
|
|
1323
|
+
--readback-ok "$READBACK_OK" \
|
|
1324
|
+
--readback-reason "$CLI_READBACK_REASON" \
|
|
1325
|
+
--shot-ok "$CLI_SHOT_OK" \
|
|
1326
|
+
--shot-reason "$CLI_SHOT_REASON" \
|
|
1063
1327
|
--suppressed "$SUPPRESSED" \
|
|
1064
1328
|
--suppressed-json "$SUPPRESSED_JSON" \
|
|
1065
1329
|
--huge "$DIFF_HUGE" \
|
|
1066
1330
|
--tiny "$DIFF_TINY" \
|
|
1067
|
-
--failure-summary "$
|
|
1331
|
+
--failure-summary "$CLI_FAILURE_SUMMARY" \
|
|
1068
1332
|
--url-reason "$RECAP_URL_REASON" \
|
|
1069
1333
|
--workflow-url "$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-native/recap-cli",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.68-nightly-20261009011246",
|
|
4
4
|
"description": "Dependency-light PR visual recap CLI for Agent-Native workflows.",
|
|
5
5
|
"homepage": "https://github.com/BuilderIO/agent-native#readme",
|
|
6
6
|
"bugs": {
|