pullfrog 0.1.45 → 0.1.47

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/internal.js CHANGED
@@ -381,6 +381,28 @@ var providers = {
381
381
  }
382
382
  }
383
383
  }),
384
+ "openai-compatible": provider({
385
+ // "Custom" is the picker group, "OpenAI-compatible" the entry under it, so the
386
+ // menu reads `Custom › OpenAI-compatible` and a second custom backend (a
387
+ // different wire format, say) slots in beside it without a rename. the
388
+ // provider KEY stays `openai-compatible` — it's the stored slug and the
389
+ // `OPENAI_COMPATIBLE_*` env prefix, so this is display-only.
390
+ displayName: "Custom",
391
+ // bring-your-own generic OpenAI-compatible endpoint — Cloudflare AI Gateway,
392
+ // Alibaba DashScope, self-hosted vLLM, or any compatible gateway. base URL +
393
+ // key + model ID are all supplied via env; nothing is cataloged or bumped.
394
+ envVars: ["OPENAI_COMPATIBLE_BASE_URL", "OPENAI_COMPATIBLE_API_KEY", "OPENAI_COMPATIBLE_MODEL"],
395
+ models: {
396
+ // single routing entry — the actual model ID is read from
397
+ // OPENAI_COMPATIBLE_MODEL at run time and the provider is materialized
398
+ // via `@ai-sdk/openai-compatible`.
399
+ byok: {
400
+ displayName: "OpenAI-compatible",
401
+ resolve: "openai-compatible",
402
+ routing: "openai-compatible"
403
+ }
404
+ }
405
+ }),
384
406
  openrouter: provider({
385
407
  displayName: "OpenRouter",
386
408
  envVars: ["OPENROUTER_API_KEY"],
@@ -1307,6 +1329,113 @@ async function createLeapingProgressComment(ctx, target, body) {
1307
1329
  };
1308
1330
  }
1309
1331
 
1332
+ // utils/runStatusCheck.ts
1333
+ var RUN_STATUS_CHECK_NAME = "Pullfrog";
1334
+ var APPROVAL_CHECK_NAME = "Pullfrog approval";
1335
+ var IN_PROGRESS_OUTPUT = {
1336
+ title: "Pullfrog is running",
1337
+ summary: "Pullfrog is working on this pull request. This check updates when the run finishes."
1338
+ };
1339
+ function disableCheckLine(owner, repo) {
1340
+ const url = `https://pullfrog.com/console/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}#auto-review-prs`;
1341
+ return `
1342
+
1343
+ [Turn off this check \u2192](${url}) \u2014 it reports run status only and gates nothing unless you required it in branch protection.`;
1344
+ }
1345
+ var TERMINAL_OUTPUT = {
1346
+ success: {
1347
+ title: "Pullfrog run completed",
1348
+ summary: "The Pullfrog run finished successfully."
1349
+ },
1350
+ failure: {
1351
+ title: "Pullfrog run failed",
1352
+ summary: "The Pullfrog run failed. See the run logs for details."
1353
+ },
1354
+ cancelled: {
1355
+ title: "Pullfrog run cancelled",
1356
+ summary: "The Pullfrog run was cancelled before it finished."
1357
+ },
1358
+ timed_out: {
1359
+ title: "Pullfrog run timed out",
1360
+ summary: "The Pullfrog run exceeded its timeout. See the run logs for details."
1361
+ },
1362
+ action_required: {
1363
+ title: "Pullfrog run needs attention",
1364
+ summary: "The Pullfrog run stopped and needs attention. See the run logs for details."
1365
+ },
1366
+ neutral: {
1367
+ title: "Pullfrog run finished",
1368
+ summary: "The Pullfrog run finished without a pass or fail outcome."
1369
+ },
1370
+ skipped: {
1371
+ title: "Pullfrog run skipped",
1372
+ summary: "This run was superseded by another Pullfrog run."
1373
+ },
1374
+ stale: {
1375
+ title: "Pullfrog run didn't finish",
1376
+ summary: "Pullfrog never received a completion signal for this run. See the run logs for details."
1377
+ }
1378
+ };
1379
+ function terminalOutput(params) {
1380
+ const base = TERMINAL_OUTPUT[params.conclusion];
1381
+ const review = params.reviewUrl ? `
1382
+
1383
+ [View the review Pullfrog posted \u2192](${params.reviewUrl})` : "";
1384
+ const disable = params.conclusion === "success" ? "" : disableCheckLine(params.owner, params.repo);
1385
+ return { title: base.title, summary: base.summary + review + disable };
1386
+ }
1387
+ async function createRunStatusCheck(params) {
1388
+ const existing = await params.octokit.rest.checks.listForRef({
1389
+ owner: params.owner,
1390
+ repo: params.repo,
1391
+ ref: params.headSha,
1392
+ check_name: RUN_STATUS_CHECK_NAME,
1393
+ status: "in_progress"
1394
+ }).catch(() => void 0);
1395
+ const reusable = existing?.data.check_runs[0];
1396
+ if (reusable) return reusable.id;
1397
+ const createParams = {
1398
+ owner: params.owner,
1399
+ repo: params.repo,
1400
+ name: RUN_STATUS_CHECK_NAME,
1401
+ head_sha: params.headSha,
1402
+ status: "in_progress",
1403
+ output: IN_PROGRESS_OUTPUT
1404
+ };
1405
+ if (params.detailsUrl) createParams.details_url = params.detailsUrl;
1406
+ const created = await params.octokit.rest.checks.create(createParams);
1407
+ return created.data.id;
1408
+ }
1409
+ async function finalizeRunStatusCheck(params) {
1410
+ const updateParams = {
1411
+ owner: params.owner,
1412
+ repo: params.repo,
1413
+ check_run_id: params.checkRunId,
1414
+ status: "completed",
1415
+ conclusion: params.conclusion,
1416
+ output: terminalOutput({
1417
+ conclusion: params.conclusion,
1418
+ owner: params.owner,
1419
+ repo: params.repo,
1420
+ reviewUrl: params.reviewUrl
1421
+ })
1422
+ };
1423
+ if (params.detailsUrl) updateParams.details_url = params.detailsUrl;
1424
+ await params.octokit.rest.checks.update(updateParams);
1425
+ }
1426
+ async function runStatusCheckNeedsFinalizing(params) {
1427
+ try {
1428
+ const existing = await params.octokit.rest.checks.get({
1429
+ owner: params.owner,
1430
+ repo: params.repo,
1431
+ check_run_id: params.checkRunId
1432
+ });
1433
+ return existing.data.status !== "completed";
1434
+ } catch {
1435
+ return false;
1436
+ }
1437
+ }
1438
+
1310
1439
  // utils/time.ts
1311
1440
  var TIMEOUT_DISABLED = "none";
1312
1441
  var TIME_STRING_REGEX = /^(?:(\d+)h)?(?:(\d+)m)?(?:(\d+)s)?$/;
@@ -1322,6 +1451,7 @@ function isValidTimeString(input) {
1322
1451
  return parseTimeString(input) !== null;
1323
1452
  }
1324
1453
  export {
1454
+ APPROVAL_CHECK_NAME,
1325
1455
  AUTO_EFFICIENT,
1326
1456
  AUTO_INTELLIGENT,
1327
1457
  DEFAULT_PROXY_MODEL,
@@ -1329,12 +1459,15 @@ export {
1329
1459
  MAX_LEARNINGS_LENGTH,
1330
1460
  OAuthInvalidGrantError,
1331
1461
  PULLFROG_DIVIDER,
1462
+ RUN_STATUS_CHECK_NAME,
1332
1463
  TIMEOUT_DISABLED,
1333
1464
  buildPullfrogFooter,
1334
1465
  createLeapingProgressComment,
1466
+ createRunStatusCheck,
1335
1467
  decodeJwtExpMs,
1336
1468
  defaultAutoTier,
1337
1469
  deleteProgressCommentApi,
1470
+ finalizeRunStatusCheck,
1338
1471
  getAutoSelectHintModel,
1339
1472
  getModelEnvVars,
1340
1473
  getModelManagedCredentials,
@@ -1358,6 +1491,7 @@ export {
1358
1491
  resolveDisplayAlias,
1359
1492
  resolveModelSlug,
1360
1493
  resolveOpenRouterModel,
1494
+ runStatusCheckNeedsFinalizing,
1361
1495
  stringifyCodexAuthBody,
1362
1496
  stripExistingFooter,
1363
1497
  truncateAtLineBoundary,
package/dist/models.d.ts CHANGED
@@ -20,7 +20,7 @@
20
20
  * env var and routes to claude-code for Anthropic IDs or opencode for
21
21
  * everything else.
22
22
  */
23
- export type ModelRouting = "bedrock" | "vertex";
23
+ export type ModelRouting = "bedrock" | "vertex" | "openai-compatible";
24
24
  export interface ModelAlias {
25
25
  /** stable alias stored in DB, e.g. "anthropic/claude-opus" */
26
26
  slug: string;
@@ -99,6 +99,7 @@ export declare const providers: {
99
99
  "opencode-go": ProviderConfig;
100
100
  bedrock: ProviderConfig;
101
101
  vertex: ProviderConfig;
102
+ "openai-compatible": ProviderConfig;
102
103
  openrouter: ProviderConfig;
103
104
  };
104
105
  export type ModelProvider = keyof typeof providers;
@@ -196,6 +197,31 @@ export declare function getAutoSelectHintModel(): string;
196
197
  export declare const BEDROCK_MODEL_ID_ENV = "BEDROCK_MODEL_ID";
197
198
  /** env var that supplies the Vertex AI model ID for the `vertex/byok` slug. */
198
199
  export declare const VERTEX_MODEL_ID_ENV = "VERTEX_MODEL_ID";
200
+ /** provider key + slug prefix for the generic OpenAI-compatible BYOK backend. */
201
+ export declare const OPENAI_COMPATIBLE_PROVIDER = "openai-compatible";
202
+ /** base URL of the user's OpenAI-compatible endpoint (e.g. a Cloudflare AI Gateway URL). */
203
+ export declare const OPENAI_COMPATIBLE_BASE_URL_ENV = "OPENAI_COMPATIBLE_BASE_URL";
204
+ /** API key/token for the user's OpenAI-compatible endpoint — the one sensitive secret. */
205
+ export declare const OPENAI_COMPATIBLE_API_KEY_ENV = "OPENAI_COMPATIBLE_API_KEY";
206
+ /** model ID served by the endpoint, supplied for the `openai-compatible/byok` slug. */
207
+ export declare const OPENAI_COMPATIBLE_MODEL_ENV = "OPENAI_COMPATIBLE_MODEL";
208
+ /**
209
+ * context-window size of the endpoint's model. required — `validateOpenAICompatibleSetup`
210
+ * rejects the run pre-agent when it's unset or non-numeric. it also gates
211
+ * auto-compaction: opencode's `isOverflow` short-circuits when
212
+ * `limit.context === 0`, which would otherwise let a long session grow until the
213
+ * endpoint rejects it on context length.
214
+ */
215
+ export declare const OPENAI_COMPATIBLE_CONTEXT_ENV = "OPENAI_COMPATIBLE_CONTEXT";
216
+ /**
217
+ * max completion tokens the endpoint's model accepts. required — see
218
+ * OPENAI_COMPATIBLE_CONTEXT_ENV. opencode has no models.dev metadata for a
219
+ * user-supplied endpoint, and an undeclared limit makes it send
220
+ * `max_tokens: 32000`, which most models reject outright (gpt-4o and gpt-4o-mini
221
+ * cap at 16384, many open models at 4096/8192). opencode's `limit` requires
222
+ * `context` + `output` together, so the pair is validated and emitted as a unit.
223
+ */
224
+ export declare const OPENAI_COMPATIBLE_MAX_OUTPUT_ENV = "OPENAI_COMPATIBLE_MAX_OUTPUT";
199
225
  /**
200
226
  * the Bedrock model ID passed to claude-code or opencode is whatever the
201
227
  * user set in `BEDROCK_MODEL_ID` — Pullfrog never resolves or upgrades it.
@@ -104,6 +104,7 @@ export interface ToolState {
104
104
  approval?: {
105
105
  wouldApprove: boolean;
106
106
  sha: string | undefined;
107
+ url?: string | undefined;
107
108
  };
108
109
  reviewReplies?: Map<number, {
109
110
  commentId: number;
@@ -1,3 +1,10 @@
1
+ /**
2
+ * marker for the distinct "run-context couldn't hand over your stored secrets"
3
+ * body. surfaced verbatim by `runErrorRenderer` (same contract as
4
+ * `MODEL_ACCESS_MARKER`) because blaming the user for a transient fetch failure
5
+ * on our side is the wrong CTA — their key is configured and still stored.
6
+ */
7
+ export declare const SECRETS_UNAVAILABLE_MARKER = "couldn't load your Pullfrog secrets";
1
8
  /**
2
9
  * Validate that the resolved model can actually be served by the chosen
3
10
  * agent. For routing slugs (Bedrock / Vertex) the auth shape is multi-var
@@ -16,6 +23,9 @@ export declare function validateAgentApiKey(params: {
16
23
  authorized: Set<string>;
17
24
  owner: string;
18
25
  name: string;
26
+ /** run-context couldn't hand over Pullfrog-stored secrets, so a missing key
27
+ * says nothing about what the user actually configured. */
28
+ secretsUnavailable?: boolean | undefined;
19
29
  }): void;
20
30
  /**
21
31
  * Detect agent-runtime auth failures that should be reformatted as an actionable
@@ -22,6 +22,9 @@ export declare const JsonPayload: import("arktype/internal/variants/object.ts").
22
22
  id: string;
23
23
  type: "issue" | "review";
24
24
  } | undefined;
25
+ checkRun?: {
26
+ id: string;
27
+ } | undefined;
25
28
  generateSummary?: boolean | undefined;
26
29
  }, {}>;
27
30
  export declare const Inputs: import("arktype/internal/variants/object.ts").ObjectType<{
@@ -68,10 +71,14 @@ export declare function resolvePayload(resolvedPromptInput: ResolvedPromptInput,
68
71
  id: string;
69
72
  type: "issue" | "review";
70
73
  } | undefined;
74
+ checkRun: {
75
+ id: string;
76
+ } | undefined;
71
77
  generateSummary: boolean | undefined;
72
78
  push: import("../external.ts").PushPermission;
73
79
  shell: import("../external.ts").ShellPermission;
74
- statusChecks: boolean;
80
+ runStatusCheck: boolean;
81
+ approvalCheck: boolean;
75
82
  progressComments: boolean;
76
83
  proxyModel: string | undefined;
77
84
  };
@@ -34,6 +34,7 @@ export interface RepoSettings {
34
34
  autoMergeEnabled: boolean;
35
35
  signedCommits: boolean;
36
36
  progressComments: boolean;
37
+ statusChecks: boolean;
37
38
  modeInstructions: Record<string, string>;
38
39
  learnings: string | null;
39
40
  learningsHeadings: LearningsHeading[];
@@ -55,6 +56,13 @@ export interface RunContext {
55
56
  plan: AccountPlan;
56
57
  proxyModel?: string | undefined;
57
58
  dbSecrets?: Record<string, string> | undefined;
59
+ /**
60
+ * the server tried and failed to materialize Pullfrog-stored secrets (or we
61
+ * never got a usable response at all). distinct from an absent `dbSecrets`,
62
+ * which legitimately means the user has none stored — without the
63
+ * distinction a transient failure renders as "you have no API key".
64
+ */
65
+ secretsUnavailable?: boolean | undefined;
58
66
  }
59
67
  /**
60
68
  * fetch run context from Pullfrog API
@@ -13,6 +13,9 @@ export interface RunContextData {
13
13
  plan: AccountPlan;
14
14
  proxyModel?: string | undefined;
15
15
  dbSecrets?: Record<string, string> | undefined;
16
+ /** stored secrets couldn't be materialized for this run — not the same as
17
+ * the user having none. see `RunContext.secretsUnavailable`. */
18
+ secretsUnavailable?: boolean | undefined;
16
19
  }
17
20
  interface ResolveRunContextDataParams {
18
21
  octokit: OctokitWithPlugins;
@@ -0,0 +1,170 @@
1
+ /**
2
+ * Single source of truth for the `pullfrog` commit-status check-run — the row a PR's
3
+ * checks list shows while a run is in flight and after it ends.
4
+ *
5
+ * Pullfrog dispatches its workflow with `ref: <default branch>`, so the GitHub Actions
6
+ * run attaches its check suite to the default branch head and never to the PR head.
7
+ * Nothing about a run is therefore visible from the PR itself unless we post this
8
+ * check-run against the PR head sha ourselves.
9
+ *
10
+ * Created `in_progress` by the server at dispatch — before the runner boots, and
11
+ * upstream of every action-side failure that would otherwise leave the PR silent
12
+ * (billing 402, token resolution, bad model slug, missing provider key). Moved to a
13
+ * terminal conclusion by whichever of three actors reaches it first, all calling
14
+ * `finalizeRunStatusCheck`:
15
+ *
16
+ * 1. the action at run end (`reportStatusChecks`)
17
+ * 2. the `workflow_run.completed` webhook (covers cancel / SIGKILL / early throw)
18
+ * 3. the hourly stuck-run reaper (covers a dropped webhook)
19
+ *
20
+ * That three-layer close-out is what makes an `in_progress` check safe here: a check
21
+ * stranded `in_progress` on a required branch-protection rule would block merges
22
+ * forever, which is why this file did not exist before.
23
+ */
24
+ /**
25
+ * the run-lifecycle check. verdict-agnostic — it reports that a run happened, not what it
26
+ * found. this string IS the branch-protection identifier, so changing it silently breaks
27
+ * any repo that required the old name.
28
+ */
29
+ export declare const RUN_STATUS_CHECK_NAME = "Pullfrog";
30
+ /** the review-verdict check. opt-in, terminal-only, and deliberately separate from the above. */
31
+ export declare const APPROVAL_CHECK_NAME = "Pullfrog approval";
32
+ /**
33
+ * The terminal states we report. Exactly GitHub's check-run `conclusion` enum, which
34
+ * happens to be `WorkflowRunStatus` minus `running` — so the server can map a finished
35
+ * run's status straight across (`checkConclusionFromStatus` in utils/workflowRunStatus.ts).
36
+ */
37
+ export type RunStatusCheckConclusion = "success" | "failure" | "cancelled" | "timed_out" | "action_required" | "neutral" | "skipped" | "stale";
38
+ /**
39
+ * Parse the on-the-wire `{ id: string }` shape (the form carried in `JsonPayload`) into
40
+ * a check-run id. Mirrors `parseProgressComment` — returns undefined when the id isn't a
41
+ * positive integer so callers can short-circuit cleanly.
42
+ */
43
+ export declare function parseCheckRunId(raw: {
44
+ id: string;
45
+ } | null | undefined): number | undefined;
46
+ interface CheckRunResponse {
47
+ data: {
48
+ id: number;
49
+ };
50
+ }
51
+ type CheckRunStatus = "queued" | "in_progress" | "completed";
52
+ type CheckRunOutput = {
53
+ title: string;
54
+ summary: string;
55
+ };
56
+ type CreateCheckRunParams = {
57
+ owner: string;
58
+ repo: string;
59
+ name: string;
60
+ head_sha: string;
61
+ status?: CheckRunStatus;
62
+ conclusion?: RunStatusCheckConclusion;
63
+ details_url?: string;
64
+ output?: CheckRunOutput;
65
+ };
66
+ type UpdateCheckRunParams = {
67
+ owner: string;
68
+ repo: string;
69
+ check_run_id: number;
70
+ status?: CheckRunStatus;
71
+ conclusion?: RunStatusCheckConclusion;
72
+ details_url?: string;
73
+ output?: CheckRunOutput;
74
+ };
75
+ export interface RunStatusCheckOctokit {
76
+ rest: {
77
+ checks: {
78
+ create: (params: CreateCheckRunParams) => Promise<CheckRunResponse>;
79
+ update: (params: UpdateCheckRunParams) => Promise<CheckRunResponse>;
80
+ get: (params: {
81
+ owner: string;
82
+ repo: string;
83
+ check_run_id: number;
84
+ }) => Promise<{
85
+ data: {
86
+ status: string;
87
+ };
88
+ }>;
89
+ listForRef: (params: {
90
+ owner: string;
91
+ repo: string;
92
+ ref: string;
93
+ check_name?: string;
94
+ status?: "queued" | "in_progress" | "completed";
95
+ }) => Promise<{
96
+ data: {
97
+ check_runs: {
98
+ id: number;
99
+ }[];
100
+ };
101
+ }>;
102
+ };
103
+ };
104
+ }
105
+ /**
106
+ * Post the `in_progress` check-run on `headSha` and return its id for the finalizers.
107
+ *
108
+ * Best-effort: a transient 5xx, a repo that revoked `checks: write`, or a PR whose head
109
+ * has already been deleted must never stop a run from dispatching. Returns undefined on
110
+ * failure, which every caller treats as "no check to finalize".
111
+ */
112
+ export declare function createRunStatusCheck(params: {
113
+ octokit: RunStatusCheckOctokit;
114
+ owner: string;
115
+ repo: string;
116
+ headSha: string;
117
+ detailsUrl: string | undefined;
118
+ }): Promise<number | undefined>;
119
+ /**
120
+ * Move an existing check-run to its terminal conclusion.
121
+ *
122
+ * A PATCH, not a second create: `POST /check-runs` with the same name + sha creates a
123
+ * SECOND row rather than replacing the first, so creating twice would show the PR two
124
+ * contradictory `pullfrog` rows. (That is a real bug today — `finalizeSuccessRun` posts
125
+ * success and a later throw posts failure, both as fresh rows.)
126
+ */
127
+ export declare function finalizeRunStatusCheck(params: {
128
+ octokit: RunStatusCheckOctokit;
129
+ owner: string;
130
+ repo: string;
131
+ checkRunId: number;
132
+ conclusion: RunStatusCheckConclusion;
133
+ detailsUrl: string | undefined;
134
+ reviewUrl?: string | undefined;
135
+ }): Promise<void>;
136
+ /**
137
+ * Post an already-terminal check-run in one call.
138
+ *
139
+ * The fallback for runs that never got a server-created check to update: a rolling
140
+ * deploy where the dispatch payload predates `checkRun`, or a workflow invoked outside
141
+ * Pullfrog's own dispatch path (`prompt_file`, a hand-written step).
142
+ */
143
+ export declare function createTerminalRunStatusCheck(params: {
144
+ octokit: RunStatusCheckOctokit;
145
+ owner: string;
146
+ repo: string;
147
+ headSha: string;
148
+ conclusion: RunStatusCheckConclusion;
149
+ detailsUrl: string | undefined;
150
+ reviewUrl?: string | undefined;
151
+ }): Promise<void>;
152
+ /**
153
+ * Whether this check still needs finalizing.
154
+ *
155
+ * The server-side close-outs are BACKSTOPS: they exist for runs the action could not
156
+ * finalize itself. Firing them unconditionally is actively harmful, because the action
157
+ * writes a richer summary than they can — it knows the review URL, they do not — so a
158
+ * blind re-PATCH silently strips that link seconds after it appears. It also resets
159
+ * `completed_at`, discarding the duration GitHub renders as "Successful in 2m".
160
+ *
161
+ * Returns false when GitHub cannot be reached: a backstop that cannot confirm the check
162
+ * is unfinished must not overwrite a good one.
163
+ */
164
+ export declare function runStatusCheckNeedsFinalizing(params: {
165
+ octokit: RunStatusCheckOctokit;
166
+ owner: string;
167
+ repo: string;
168
+ checkRunId: number;
169
+ }): Promise<boolean>;
170
+ export {};
@@ -1,24 +1,21 @@
1
1
  import type { ToolContext } from "../mcp/server.ts";
2
2
  /**
3
- * post the opt-in `pullfrog` (run completion) and `pullfrog-approval` (review
4
- * verdict) commit-status check-runs so they can be required by branch
5
- * protection. no-op unless the `status_checks` input is enabled and the run is
6
- * on a pull request.
3
+ * post the `Pullfrog` (run lifecycle) and `Pullfrog approval` (review verdict)
4
+ * commit-status check-runs.
7
5
  *
8
- * terminal-only by design: we never create an `in_progress` check. a
9
- * hard-cancelled run (SIGKILL) would strand a required check `in_progress` and
10
- * block merges forever; an absent required check already blocks merge the same
11
- * way while the run is in flight, with no stuck-check failure mode.
6
+ * - `Pullfrog` is on by default (`Repo.statusChecks`). the server already created it
7
+ * `in_progress` at dispatch, so the work here is a PATCH to its terminal conclusion —
8
+ * see `runStatusCheck.ts` for why a second create would leave two contradictory rows.
9
+ * the terminal-create fallback covers a payload with no `checkRun` (older server
10
+ * build mid-rolling-deploy, or a workflow driven outside Pullfrog's dispatch path).
11
+ * - `Pullfrog approval` stays opt-in (`status_checks: enabled`) and terminal-only:
12
+ * it asserts a review verdict, which only exists once a run produces one. anchored
13
+ * to the exact reviewed sha so a mid-run push leaves the new head unapproved until
14
+ * a follow-up re-review reports.
12
15
  *
13
- * - `pullfrog` is posted on every PR run: success iff the run finished
14
- * successfully, failure on error/timeout. review-verdict-agnostic.
15
- * - `pullfrog-approval` is posted only when this run produced an approval
16
- * verdict (`toolState.approval`, set by create_pull_request_review),
17
- * anchored to the reviewed sha so a mid-run push leaves the new head
18
- * unapproved until the follow-up re-review reports.
19
- *
20
- * best-effort throughout: a check-post failure (fork PR head not in the base
21
- * repo, transient 5xx, closed PR) must never flip the run's own outcome.
16
+ * best-effort throughout: a check-post failure (transient 5xx, closed PR, revoked
17
+ * permission) must never flip the run's own outcome. the `workflow_run.completed` webhook
18
+ * and both stuck-run reaper sweeps close out a check this function fails to finalize.
22
19
  */
23
20
  export declare function reportStatusChecks(ctx: ToolContext, params: {
24
21
  runSucceeded: boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pullfrog",
3
- "version": "0.1.45",
3
+ "version": "0.1.47",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "pullfrog": "dist/cli.mjs",