@sentry/junior-github 0.89.0 → 0.90.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/SETUP.md +2 -1
- package/dist/index.js +113 -17
- package/dist/tools/create-issue.d.ts +28 -11
- package/dist/tools/create-pull-request.d.ts +46 -13
- package/package.json +3 -2
- package/skills/github-code/SKILL.md +2 -1
- package/skills/github-code/references/api-surface.md +2 -1
- package/skills/github-code/references/troubleshooting-workarounds.md +1 -0
package/SETUP.md
CHANGED
|
@@ -153,13 +153,14 @@ For PR creation in automation, push explicitly and pass that branch as `head`:
|
|
|
153
153
|
|
|
154
154
|
```bash
|
|
155
155
|
git -C repo push -u origin BRANCH
|
|
156
|
+
gh repo view owner/repo --json defaultBranchRef --jq .defaultBranchRef.name
|
|
156
157
|
```
|
|
157
158
|
|
|
158
159
|
```ts
|
|
159
160
|
github_createPullRequest({
|
|
160
161
|
repo: "owner/repo",
|
|
161
162
|
head: "BRANCH",
|
|
162
|
-
base: "
|
|
163
|
+
base: "<DEFAULT_BRANCH>",
|
|
163
164
|
title: "Example PR",
|
|
164
165
|
body: "Example body",
|
|
165
166
|
draft: true,
|
package/dist/index.js
CHANGED
|
@@ -72,11 +72,14 @@ function permissionCapabilities(permissions) {
|
|
|
72
72
|
|
|
73
73
|
// src/tools/create-issue.ts
|
|
74
74
|
import {
|
|
75
|
+
definePluginTool,
|
|
75
76
|
EgressAuthRequired,
|
|
76
|
-
PluginToolInputError as PluginToolInputError2
|
|
77
|
+
PluginToolInputError as PluginToolInputError2,
|
|
78
|
+
pluginToolResultSchema
|
|
77
79
|
} from "@sentry/junior-plugin-api";
|
|
78
80
|
import { Type } from "@sinclair/typebox";
|
|
79
81
|
import { Value } from "@sinclair/typebox/value";
|
|
82
|
+
import { z } from "zod";
|
|
80
83
|
|
|
81
84
|
// src/tools/footer.ts
|
|
82
85
|
import { PluginToolInputError } from "@sentry/junior-plugin-api";
|
|
@@ -179,6 +182,12 @@ var createIssueInputSchema = Type.Object(
|
|
|
179
182
|
},
|
|
180
183
|
{ additionalProperties: false }
|
|
181
184
|
);
|
|
185
|
+
var createIssueToolInputSchema = z.object({
|
|
186
|
+
repo: z.string().describe('Repository in "owner/name" format.'),
|
|
187
|
+
title: z.string().describe("Issue title."),
|
|
188
|
+
body: z.string().describe("Issue body. Junior appends the conversation footer.").optional(),
|
|
189
|
+
labels: z.array(z.string()).describe("Labels to apply to the issue.").optional()
|
|
190
|
+
}).strict();
|
|
182
191
|
var createIssueStateSchema = Type.Union([
|
|
183
192
|
Type.Object(
|
|
184
193
|
{
|
|
@@ -197,6 +206,27 @@ var createIssueStateSchema = Type.Union([
|
|
|
197
206
|
{ additionalProperties: false }
|
|
198
207
|
)
|
|
199
208
|
]);
|
|
209
|
+
var gitHubIssueDataSchema = z.object({
|
|
210
|
+
number: z.number(),
|
|
211
|
+
url: z.string()
|
|
212
|
+
});
|
|
213
|
+
var gitHubIssueOutputSchema = pluginToolResultSchema.extend({
|
|
214
|
+
ok: z.literal(true),
|
|
215
|
+
status: z.literal("success"),
|
|
216
|
+
target: z.literal("createIssue"),
|
|
217
|
+
data: gitHubIssueDataSchema,
|
|
218
|
+
number: z.number(),
|
|
219
|
+
url: z.string()
|
|
220
|
+
});
|
|
221
|
+
function gitHubIssueToolResult(result) {
|
|
222
|
+
return {
|
|
223
|
+
ok: true,
|
|
224
|
+
status: "success",
|
|
225
|
+
target: "createIssue",
|
|
226
|
+
data: result,
|
|
227
|
+
...result
|
|
228
|
+
};
|
|
229
|
+
}
|
|
200
230
|
function parseCreateIssueInput(input) {
|
|
201
231
|
try {
|
|
202
232
|
return Value.Parse(createIssueInputSchema, input);
|
|
@@ -320,9 +350,10 @@ async function createGitHubIssue(ctx, request) {
|
|
|
320
350
|
};
|
|
321
351
|
}
|
|
322
352
|
function createGitHubIssueTool(ctx) {
|
|
323
|
-
return {
|
|
353
|
+
return definePluginTool({
|
|
324
354
|
description: "Create a GitHub issue with a runtime-owned Junior conversation footer. Use this instead of shelling out to gh issue create when creating issues.",
|
|
325
|
-
inputSchema:
|
|
355
|
+
inputSchema: createIssueToolInputSchema,
|
|
356
|
+
outputSchema: gitHubIssueOutputSchema,
|
|
326
357
|
async execute(input, options) {
|
|
327
358
|
const parsedInput = parseCreateIssueInput(input);
|
|
328
359
|
const conversationId = nonEmptyString2(
|
|
@@ -337,10 +368,10 @@ function createGitHubIssueTool(ctx) {
|
|
|
337
368
|
async () => {
|
|
338
369
|
const state = createIssueState(await ctx.state.get(key));
|
|
339
370
|
if (state?.status === "completed") {
|
|
340
|
-
return {
|
|
371
|
+
return gitHubIssueToolResult({
|
|
341
372
|
number: state.number,
|
|
342
373
|
url: state.url
|
|
343
|
-
};
|
|
374
|
+
});
|
|
344
375
|
}
|
|
345
376
|
if (state?.status === "pending") {
|
|
346
377
|
throw new Error(
|
|
@@ -372,7 +403,7 @@ function createGitHubIssueTool(ctx) {
|
|
|
372
403
|
{ cause: error }
|
|
373
404
|
);
|
|
374
405
|
}
|
|
375
|
-
return result;
|
|
406
|
+
return gitHubIssueToolResult(result);
|
|
376
407
|
} catch (error) {
|
|
377
408
|
if (isEgressAuthRequired(error) || isDefinitiveGitHubIssueCreateRejection(error)) {
|
|
378
409
|
await ctx.state.delete(key);
|
|
@@ -382,16 +413,19 @@ function createGitHubIssueTool(ctx) {
|
|
|
382
413
|
}
|
|
383
414
|
);
|
|
384
415
|
}
|
|
385
|
-
};
|
|
416
|
+
});
|
|
386
417
|
}
|
|
387
418
|
|
|
388
419
|
// src/tools/create-pull-request.ts
|
|
389
420
|
import {
|
|
421
|
+
definePluginTool as definePluginTool2,
|
|
390
422
|
EgressAuthRequired as EgressAuthRequired2,
|
|
391
|
-
PluginToolInputError as PluginToolInputError3
|
|
423
|
+
PluginToolInputError as PluginToolInputError3,
|
|
424
|
+
pluginToolResultSchema as pluginToolResultSchema2
|
|
392
425
|
} from "@sentry/junior-plugin-api";
|
|
393
426
|
import { Type as Type2 } from "@sinclair/typebox";
|
|
394
427
|
import { Value as Value2 } from "@sinclair/typebox/value";
|
|
428
|
+
import { z as z2 } from "zod";
|
|
395
429
|
var GITHUB_PULL_REQUEST_CREATE_IDEMPOTENCY_TTL_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
396
430
|
var GITHUB_PULL_REQUEST_CREATE_LOCK_TTL_MS = 6e4;
|
|
397
431
|
var GitHubPullRequestCreateRejectedError = class extends Error {
|
|
@@ -429,6 +463,14 @@ var createPullRequestInputSchema = Type2.Object(
|
|
|
429
463
|
},
|
|
430
464
|
{ additionalProperties: false }
|
|
431
465
|
);
|
|
466
|
+
var createPullRequestToolInputSchema = z2.object({
|
|
467
|
+
repo: z2.string().describe('Repository in "owner/name" format.'),
|
|
468
|
+
title: z2.string().describe("Pull request title."),
|
|
469
|
+
head: z2.string().describe("Head branch or owner:branch ref."),
|
|
470
|
+
base: z2.string().describe("Base branch."),
|
|
471
|
+
body: z2.string().describe("Pull request body. Junior appends the conversation footer.").optional(),
|
|
472
|
+
draft: z2.boolean().describe("Whether to open the pull request as a draft.").optional()
|
|
473
|
+
}).strict();
|
|
432
474
|
var createPullRequestStateSchema = Type2.Union([
|
|
433
475
|
Type2.Object(
|
|
434
476
|
{
|
|
@@ -449,6 +491,28 @@ var createPullRequestStateSchema = Type2.Union([
|
|
|
449
491
|
{ additionalProperties: false }
|
|
450
492
|
)
|
|
451
493
|
]);
|
|
494
|
+
var subscribableResourceSchema = z2.object({
|
|
495
|
+
provider: z2.string(),
|
|
496
|
+
type: z2.string(),
|
|
497
|
+
resourceRef: z2.string(),
|
|
498
|
+
label: z2.string(),
|
|
499
|
+
supportedEvents: z2.array(z2.string()),
|
|
500
|
+
suggestedEvents: z2.array(z2.string()).optional()
|
|
501
|
+
}).strict();
|
|
502
|
+
var gitHubPullRequestDataSchema = z2.object({
|
|
503
|
+
number: z2.number(),
|
|
504
|
+
url: z2.string(),
|
|
505
|
+
subscribable: subscribableResourceSchema.optional()
|
|
506
|
+
});
|
|
507
|
+
var gitHubPullRequestOutputSchema = pluginToolResultSchema2.extend({
|
|
508
|
+
ok: z2.literal(true),
|
|
509
|
+
status: z2.literal("success"),
|
|
510
|
+
target: z2.literal("createPullRequest"),
|
|
511
|
+
data: gitHubPullRequestDataSchema,
|
|
512
|
+
number: z2.number(),
|
|
513
|
+
url: z2.string(),
|
|
514
|
+
subscribable: subscribableResourceSchema.optional()
|
|
515
|
+
});
|
|
452
516
|
function parseCreatePullRequestInput(input) {
|
|
453
517
|
try {
|
|
454
518
|
return Value2.Parse(createPullRequestInputSchema, input);
|
|
@@ -490,7 +554,8 @@ function githubApiErrorMessage2(payload) {
|
|
|
490
554
|
if (payload && typeof payload === "object" && !Array.isArray(payload)) {
|
|
491
555
|
const message = payload.message;
|
|
492
556
|
if (typeof message === "string") {
|
|
493
|
-
|
|
557
|
+
const details = githubApiErrorDetails(payload);
|
|
558
|
+
return details ? `${message}: ${details}` : message;
|
|
494
559
|
}
|
|
495
560
|
}
|
|
496
561
|
if (typeof payload === "string" && payload.trim()) {
|
|
@@ -498,6 +563,23 @@ function githubApiErrorMessage2(payload) {
|
|
|
498
563
|
}
|
|
499
564
|
return "GitHub request failed";
|
|
500
565
|
}
|
|
566
|
+
function githubApiErrorDetails(payload) {
|
|
567
|
+
const errors = payload.errors;
|
|
568
|
+
if (!Array.isArray(errors)) {
|
|
569
|
+
return void 0;
|
|
570
|
+
}
|
|
571
|
+
const details = errors.map((error) => {
|
|
572
|
+
if (!error || typeof error !== "object" || Array.isArray(error)) {
|
|
573
|
+
return void 0;
|
|
574
|
+
}
|
|
575
|
+
const fields = ["resource", "field", "code", "message"].map((name) => {
|
|
576
|
+
const value = error[name];
|
|
577
|
+
return typeof value === "string" && value.trim() ? `${name}=${value.trim()}` : void 0;
|
|
578
|
+
}).filter((value) => value !== void 0);
|
|
579
|
+
return fields.length ? fields.join(" ") : void 0;
|
|
580
|
+
}).filter((value) => value !== void 0);
|
|
581
|
+
return details.length ? details.join("; ") : void 0;
|
|
582
|
+
}
|
|
501
583
|
function createPullRequestState(value) {
|
|
502
584
|
if (value === void 0) {
|
|
503
585
|
return void 0;
|
|
@@ -614,10 +696,21 @@ function gitHubPullRequestToolResult(input, result) {
|
|
|
614
696
|
subscribable: gitHubPullRequestSubscribable(input, result)
|
|
615
697
|
};
|
|
616
698
|
}
|
|
617
|
-
function
|
|
699
|
+
function gitHubPullRequestStructuredResult(input, result) {
|
|
700
|
+
const data = gitHubPullRequestToolResult(input, result);
|
|
618
701
|
return {
|
|
702
|
+
ok: true,
|
|
703
|
+
status: "success",
|
|
704
|
+
target: "createPullRequest",
|
|
705
|
+
data,
|
|
706
|
+
...data
|
|
707
|
+
};
|
|
708
|
+
}
|
|
709
|
+
function createGitHubPullRequestTool(ctx) {
|
|
710
|
+
return definePluginTool2({
|
|
619
711
|
description: "Create a GitHub pull request with a runtime-owned Junior conversation footer. Use this instead of shelling out to gh pr create when creating pull requests.",
|
|
620
|
-
inputSchema:
|
|
712
|
+
inputSchema: createPullRequestToolInputSchema,
|
|
713
|
+
outputSchema: gitHubPullRequestOutputSchema,
|
|
621
714
|
async execute(input, options) {
|
|
622
715
|
const parsedInput = parseCreatePullRequestInput(input);
|
|
623
716
|
const conversationId = nonEmptyString3(
|
|
@@ -632,10 +725,13 @@ function createGitHubPullRequestTool(ctx) {
|
|
|
632
725
|
async () => {
|
|
633
726
|
const state = createPullRequestState(await ctx.state.get(key));
|
|
634
727
|
if (state?.status === "completed") {
|
|
635
|
-
return
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
728
|
+
return gitHubPullRequestStructuredResult(
|
|
729
|
+
state.input ?? parsedInput,
|
|
730
|
+
{
|
|
731
|
+
number: state.number,
|
|
732
|
+
url: state.url
|
|
733
|
+
}
|
|
734
|
+
);
|
|
639
735
|
}
|
|
640
736
|
if (state?.status === "pending") {
|
|
641
737
|
throw new Error(
|
|
@@ -671,7 +767,7 @@ function createGitHubPullRequestTool(ctx) {
|
|
|
671
767
|
{ cause: error }
|
|
672
768
|
);
|
|
673
769
|
}
|
|
674
|
-
return
|
|
770
|
+
return gitHubPullRequestStructuredResult(parsedInput, result);
|
|
675
771
|
} catch (error) {
|
|
676
772
|
if (isEgressAuthRequired2(error) || isDefinitiveGitHubPullRequestCreateRejection(error)) {
|
|
677
773
|
await ctx.state.delete(key);
|
|
@@ -681,7 +777,7 @@ function createGitHubPullRequestTool(ctx) {
|
|
|
681
777
|
}
|
|
682
778
|
);
|
|
683
779
|
}
|
|
684
|
-
};
|
|
780
|
+
});
|
|
685
781
|
}
|
|
686
782
|
|
|
687
783
|
// src/tools.ts
|
|
@@ -1,12 +1,29 @@
|
|
|
1
|
-
import { type
|
|
2
|
-
import { type Static } from "@sinclair/typebox";
|
|
3
|
-
declare const createIssueInputSchema: import("@sinclair/typebox").TObject<{
|
|
4
|
-
repo: import("@sinclair/typebox").TString;
|
|
5
|
-
title: import("@sinclair/typebox").TString;
|
|
6
|
-
body: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
7
|
-
labels: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>>;
|
|
8
|
-
}>;
|
|
9
|
-
type CreateGitHubIssueInput = Static<typeof createIssueInputSchema>;
|
|
1
|
+
import { type ToolRegistrationHookContext } from "@sentry/junior-plugin-api";
|
|
10
2
|
/** Own issue creation so provider writes use host egress and the footer stays deterministic. */
|
|
11
|
-
export declare function createGitHubIssueTool(ctx: ToolRegistrationHookContext): PluginToolDefinition<
|
|
12
|
-
|
|
3
|
+
export declare function createGitHubIssueTool(ctx: ToolRegistrationHookContext): import("@sentry/junior-plugin-api").PluginToolDefinition<{
|
|
4
|
+
repo: string;
|
|
5
|
+
title: string;
|
|
6
|
+
body?: string | undefined;
|
|
7
|
+
labels?: string[] | undefined;
|
|
8
|
+
}, {
|
|
9
|
+
[x: string]: unknown;
|
|
10
|
+
ok: true;
|
|
11
|
+
status: "success";
|
|
12
|
+
target: "createIssue";
|
|
13
|
+
data: {
|
|
14
|
+
number: number;
|
|
15
|
+
url: string;
|
|
16
|
+
};
|
|
17
|
+
number: number;
|
|
18
|
+
url: string;
|
|
19
|
+
truncated?: boolean | undefined;
|
|
20
|
+
continuation?: {
|
|
21
|
+
arguments: Record<string, unknown>;
|
|
22
|
+
reason?: string | undefined;
|
|
23
|
+
} | undefined;
|
|
24
|
+
error?: string | {
|
|
25
|
+
kind: string;
|
|
26
|
+
message: string;
|
|
27
|
+
retryable?: boolean | undefined;
|
|
28
|
+
} | undefined;
|
|
29
|
+
}>;
|
|
@@ -1,14 +1,47 @@
|
|
|
1
|
-
import { type
|
|
2
|
-
import { type Static } from "@sinclair/typebox";
|
|
3
|
-
declare const createPullRequestInputSchema: import("@sinclair/typebox").TObject<{
|
|
4
|
-
repo: import("@sinclair/typebox").TString;
|
|
5
|
-
title: import("@sinclair/typebox").TString;
|
|
6
|
-
head: import("@sinclair/typebox").TString;
|
|
7
|
-
base: import("@sinclair/typebox").TString;
|
|
8
|
-
body: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
9
|
-
draft: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TBoolean>;
|
|
10
|
-
}>;
|
|
11
|
-
type CreateGitHubPullRequestInput = Static<typeof createPullRequestInputSchema>;
|
|
1
|
+
import { type ToolRegistrationHookContext } from "@sentry/junior-plugin-api";
|
|
12
2
|
/** Own PR creation so provider writes use host egress and the footer stays deterministic. */
|
|
13
|
-
export declare function createGitHubPullRequestTool(ctx: ToolRegistrationHookContext): PluginToolDefinition<
|
|
14
|
-
|
|
3
|
+
export declare function createGitHubPullRequestTool(ctx: ToolRegistrationHookContext): import("@sentry/junior-plugin-api").PluginToolDefinition<{
|
|
4
|
+
repo: string;
|
|
5
|
+
title: string;
|
|
6
|
+
head: string;
|
|
7
|
+
base: string;
|
|
8
|
+
body?: string | undefined;
|
|
9
|
+
draft?: boolean | undefined;
|
|
10
|
+
}, {
|
|
11
|
+
[x: string]: unknown;
|
|
12
|
+
ok: true;
|
|
13
|
+
status: "success";
|
|
14
|
+
target: "createPullRequest";
|
|
15
|
+
data: {
|
|
16
|
+
number: number;
|
|
17
|
+
url: string;
|
|
18
|
+
subscribable?: {
|
|
19
|
+
provider: string;
|
|
20
|
+
type: string;
|
|
21
|
+
resourceRef: string;
|
|
22
|
+
label: string;
|
|
23
|
+
supportedEvents: string[];
|
|
24
|
+
suggestedEvents?: string[] | undefined;
|
|
25
|
+
} | undefined;
|
|
26
|
+
};
|
|
27
|
+
number: number;
|
|
28
|
+
url: string;
|
|
29
|
+
truncated?: boolean | undefined;
|
|
30
|
+
continuation?: {
|
|
31
|
+
arguments: Record<string, unknown>;
|
|
32
|
+
reason?: string | undefined;
|
|
33
|
+
} | undefined;
|
|
34
|
+
error?: string | {
|
|
35
|
+
kind: string;
|
|
36
|
+
message: string;
|
|
37
|
+
retryable?: boolean | undefined;
|
|
38
|
+
} | undefined;
|
|
39
|
+
subscribable?: {
|
|
40
|
+
provider: string;
|
|
41
|
+
type: string;
|
|
42
|
+
resourceRef: string;
|
|
43
|
+
label: string;
|
|
44
|
+
supportedEvents: string[];
|
|
45
|
+
suggestedEvents?: string[] | undefined;
|
|
46
|
+
} | undefined;
|
|
47
|
+
}>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sentry/junior-github",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.90.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -24,7 +24,8 @@
|
|
|
24
24
|
],
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"@sinclair/typebox": "^0.34.49",
|
|
27
|
-
"
|
|
27
|
+
"zod": "^4.4.3",
|
|
28
|
+
"@sentry/junior-plugin-api": "0.90.0"
|
|
28
29
|
},
|
|
29
30
|
"devDependencies": {
|
|
30
31
|
"@types/node": "^25.9.1",
|
|
@@ -109,7 +109,8 @@ Before creating:
|
|
|
109
109
|
|
|
110
110
|
1. Changes committed on a non-default branch.
|
|
111
111
|
2. Push the branch explicitly: `git push -u origin BRANCH`.
|
|
112
|
-
3.
|
|
112
|
+
3. Resolve the actual default branch: `gh repo view owner/repo --json defaultBranchRef --jq .defaultBranchRef.name`.
|
|
113
|
+
4. Create with explicit targeting, using that default branch as `base`: `github_createPullRequest({ repo: "owner/repo", head: "BRANCH", base: "<DEFAULT_BRANCH>", title: "...", body: "...", draft: true })`.
|
|
113
114
|
|
|
114
115
|
Defaults:
|
|
115
116
|
|
|
@@ -32,6 +32,7 @@ Treat explicit repo flags as command-targeting safety rails, not as a credential
|
|
|
32
32
|
| Check worktree state | `git -C DIRECTORY status --short --branch` |
|
|
33
33
|
| View commit log against base | `git -C DIRECTORY log BASE..HEAD --oneline` |
|
|
34
34
|
| Diff against base | `git -C DIRECTORY diff BASE...HEAD` |
|
|
35
|
+
| Resolve default branch | `gh repo view owner/repo --json defaultBranchRef --jq .defaultBranchRef.name` |
|
|
35
36
|
| Create branch | `git -C DIRECTORY checkout -b BRANCH` |
|
|
36
37
|
| Stage and commit | `git -C DIRECTORY add -A && git -C DIRECTORY commit -m "message"` |
|
|
37
38
|
| Push branch before PR creation | `git -C DIRECTORY push -u origin BRANCH` |
|
|
@@ -64,7 +65,7 @@ jr-rpc config set github.repo owner/repo
|
|
|
64
65
|
- A local `git commit` does not call GitHub. Pushing that commit does: `git push` requires `github.contents.write` on the target repo and requester write access.
|
|
65
66
|
- REST Git commit construction also requires `github.contents.write`: `POST /git/blobs`, `POST /git/trees`, `POST /git/commits`, `POST /git/refs`, and `PATCH /git/refs/{ref}`.
|
|
66
67
|
- If the commit changes workflow files under `.github/workflows`, expect `github.workflows.write` in addition to contents write.
|
|
67
|
-
- Before `github_createPullRequest`, push the head branch explicitly
|
|
68
|
+
- Before `github_createPullRequest`, push the head branch explicitly and resolve the target repo's default branch for `base`. That push requires GitHub write access to the remote.
|
|
68
69
|
- Do not use fork creation as the normal PR path. GitHub requires Administration write plus Contents read for `POST /repos/{owner}/{repo}/forks`, and the app must be installed on both source and destination accounts.
|
|
69
70
|
- If the explicit `git push` fails with 401/403 or another access/permission error, verify the repo context and retry once. If it still fails, load troubleshooting guidance and report the exact command failure.
|
|
70
71
|
- `gh pr edit` is not a single-permission command: title/body/base/reviewer changes need pull request write permission; label, assignee, and milestone changes need issue write permission (use the `github-issues` skill); project flags are outside the current GitHub App permission guidance.
|
|
@@ -16,6 +16,7 @@ Use this table to recover quickly while keeping operations deterministic.
|
|
|
16
16
|
| 403 Forbidden | App lacks required permission on repo or install scope is too narrow. | Verify the repo context, then confirm GitHub App permissions and installation scope. |
|
|
17
17
|
| `gh auth status` shows `Token scopes: none` | Expected for GitHub App user-to-server tokens. | Do not treat this as read-only proof. Use the failed command, `permission_denied.acceptedPermissions`, and GitHub App permissions instead. |
|
|
18
18
|
| `github_createPullRequest` fails with auth/permission errors | The branch was not pushed first, or repo context is wrong. | Push the branch explicitly first, then retry `github_createPullRequest` with explicit `repo`, `head`, and `base` values. |
|
|
19
|
+
| `github_createPullRequest` fails with 422 validation on `base` | The `base` branch does not exist in the target repo. | Resolve the default branch with `gh repo view owner/repo --json defaultBranchRef --jq .defaultBranchRef.name`, then retry with that value as `base`. |
|
|
19
20
|
| `git blame`, long log history, or old commits are missing after clone | Repo was cloned shallow by design. | Deepen incrementally with `git -C DIRECTORY fetch --depth=N origin`, or `git -C DIRECTORY fetch --unshallow` when full history is required. |
|
|
20
21
|
| `sandbox setup failed (dnf install gh failed ...)` | `gh` package not available from the plugin runtime dependency bootstrap. | Report the plugin runtime bootstrap failure; do not try to repair package installation from the skill workflow. |
|
|
21
22
|
|