@neturely/okffs 0.6.0 → 0.7.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/CHANGELOG.md +12 -1
- package/README.md +12 -6
- package/dist/config.d.ts +6 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +37 -0
- package/dist/config.js.map +1 -1
- package/dist/git.d.ts +12 -0
- package/dist/git.d.ts.map +1 -1
- package/dist/git.js +31 -0
- package/dist/git.js.map +1 -1
- package/dist/github.d.ts +56 -0
- package/dist/github.d.ts.map +1 -1
- package/dist/github.js +46 -2
- package/dist/github.js.map +1 -1
- package/dist/index.js +6 -2
- package/dist/index.js.map +1 -1
- package/dist/issue_types.d.ts +5 -0
- package/dist/issue_types.d.ts.map +1 -0
- package/dist/issue_types.js +65 -0
- package/dist/issue_types.js.map +1 -0
- package/dist/tools/create_issue.d.ts +3 -0
- package/dist/tools/create_issue.d.ts.map +1 -1
- package/dist/tools/create_issue.js +51 -41
- package/dist/tools/create_issue.js.map +1 -1
- package/dist/tools/create_issues_from_list.d.ts +6 -1
- package/dist/tools/create_issues_from_list.d.ts.map +1 -1
- package/dist/tools/create_issues_from_list.js +14 -1
- package/dist/tools/create_issues_from_list.js.map +1 -1
- package/dist/tools/create_pull_request.d.ts +4 -1
- package/dist/tools/create_pull_request.d.ts.map +1 -1
- package/dist/tools/create_pull_request.js +35 -8
- package/dist/tools/create_pull_request.js.map +1 -1
- package/dist/tools/list_issues.d.ts +1 -1
- package/dist/tools/list_issues.d.ts.map +1 -1
- package/dist/tools/list_issues.js +6 -1
- package/dist/tools/list_issues.js.map +1 -1
- package/dist/tools/merge_pull_request.d.ts +17 -0
- package/dist/tools/merge_pull_request.d.ts.map +1 -0
- package/dist/tools/merge_pull_request.js +142 -0
- package/dist/tools/merge_pull_request.js.map +1 -0
- package/dist/tools/plan.d.ts +6 -1
- package/dist/tools/plan.d.ts.map +1 -1
- package/dist/tools/plan.js +16 -1
- package/dist/tools/plan.js.map +1 -1
- package/dist/tools/set_issue_fields.d.ts +3 -0
- package/dist/tools/set_issue_fields.d.ts.map +1 -1
- package/dist/tools/set_issue_fields.js +40 -32
- package/dist/tools/set_issue_fields.js.map +1 -1
- package/dist/tools/update_issue.d.ts +32 -0
- package/dist/tools/update_issue.d.ts.map +1 -0
- package/dist/tools/update_issue.js +46 -0
- package/dist/tools/update_issue.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { getIssue, extractBranchFromBody, getDefaultBranch, getRepoDefaultBranch, getOpenPullRequestForBranch, getPullRequest, getCombinedStatus, getCheckRuns, getPullRequestReview, mergePullRequest, closeIssue, addIssueComment, } from "../github.js";
|
|
3
|
+
import { config } from "../config.js";
|
|
4
|
+
export const name = "merge_pull_request";
|
|
5
|
+
export const description = "Autonomously merge a GREEN, review-resolved issue PR into the BASE branch (e.g. develop) using the configured per-tier merge method (OKFFS_BASE_MERGE_METHOD, default squash). " +
|
|
6
|
+
"This is the ONE okffs action that merges — every other tool only opens PRs and hands back. It is therefore heavily gated and OPT-IN: it does nothing unless OKFFS_AUTO_MERGE_BASE=true. " +
|
|
7
|
+
"It NEVER merges OKFFS_PROTECTED_BRANCH (e.g. main) — that stays a manual, user-driven merge/tag — and refuses entirely if OKFFS_PROTECTED_BRANCH is unset, so it can't merge into an unnamed protected branch. " +
|
|
8
|
+
"Before merging it independently verifies (not merely trusting branch-protection rules): the PR targets the base tier and not the protected branch; it is open, not a draft, and free of conflicts; all commit statuses AND check runs on the head are green (no failing or pending checks); the PR is not blocked by a required gate; and every review thread is resolved. Any unmet gate → it refuses with an actionable reason and does not merge. " +
|
|
9
|
+
"On success it merges, comments on the issue, and — when the base isn't the repo default (so GitHub's Closes #N won't auto-close) — closes the issue to complete the loop. Use for landing small review-fix / feature PRs into develop without a human merge; the develop→main promotion always stays with the user.";
|
|
10
|
+
export const inputSchema = z.object({
|
|
11
|
+
issue_number: z.number().int().positive().describe("The issue whose PR (into the base branch) should be merged"),
|
|
12
|
+
});
|
|
13
|
+
const text = (t) => ({ content: [{ type: "text", text: t }] });
|
|
14
|
+
// Poll the PR until GitHub finishes computing `mergeable` (it returns null right
|
|
15
|
+
// after a push). A few short retries; if it never settles we refuse rather than
|
|
16
|
+
// guess. Uses setTimeout (not a shell sleep) so it works inside the server.
|
|
17
|
+
async function getPullRequestWhenComputed(prNumber) {
|
|
18
|
+
let detail = await getPullRequest(prNumber);
|
|
19
|
+
for (let i = 0; detail.mergeable === null && i < 5; i++) {
|
|
20
|
+
await new Promise((r) => setTimeout(r, 800));
|
|
21
|
+
detail = await getPullRequest(prNumber);
|
|
22
|
+
}
|
|
23
|
+
return detail;
|
|
24
|
+
}
|
|
25
|
+
export async function handler(input) {
|
|
26
|
+
// ── Gate 1: opt-in ────────────────────────────────────────────────────────
|
|
27
|
+
if (!config.autoMergeBase) {
|
|
28
|
+
return text("Autonomous merge is off. okffs will not merge a PR unless OKFFS_AUTO_MERGE_BASE=true — set it to opt in " +
|
|
29
|
+
"(the develop→main promotion always stays a manual, user-driven merge regardless).");
|
|
30
|
+
}
|
|
31
|
+
// ── Gate 2: protected branch must be named ────────────────────────────────
|
|
32
|
+
if (!config.protectedBranch) {
|
|
33
|
+
return text("[okffs] Refusing to merge: OKFFS_PROTECTED_BRANCH is unset. okffs must know which branch it may never merge " +
|
|
34
|
+
"into before it merges anything — set OKFFS_PROTECTED_BRANCH (e.g. main) so autonomous merges can be confined to the base tier.");
|
|
35
|
+
}
|
|
36
|
+
const issue = await getIssue(input.issue_number);
|
|
37
|
+
const branch = extractBranchFromBody(issue.body);
|
|
38
|
+
if (!branch) {
|
|
39
|
+
return text(`Issue #${input.issue_number} has no associated branch (no **Branch:** line), so there's no PR to merge.`);
|
|
40
|
+
}
|
|
41
|
+
const baseTier = await getDefaultBranch(); // OKFFS_BASE_BRANCH or the repo default
|
|
42
|
+
// Misconfiguration guard: the base tier must not itself be the protected branch.
|
|
43
|
+
if (baseTier === config.protectedBranch) {
|
|
44
|
+
return text(`[okffs] Refusing to merge: the base branch (\`${baseTier}\`) is the same as OKFFS_PROTECTED_BRANCH. ` +
|
|
45
|
+
"okffs never autonomously merges the protected branch — set OKFFS_BASE_BRANCH to a distinct base tier (e.g. develop).");
|
|
46
|
+
}
|
|
47
|
+
const prRef = await getOpenPullRequestForBranch(branch, baseTier);
|
|
48
|
+
if (!prRef) {
|
|
49
|
+
return text(`No open PR found for branch \`${branch}\` into \`${baseTier}\`. Open one with create_pull_request first.`);
|
|
50
|
+
}
|
|
51
|
+
const pr = await getPullRequestWhenComputed(prRef.number);
|
|
52
|
+
const label = `PR #${pr.number} (${branch} → ${pr.base.ref})`;
|
|
53
|
+
// ── Gate 3: target is the base tier, never the protected branch ───────────
|
|
54
|
+
if (pr.base.ref === config.protectedBranch) {
|
|
55
|
+
return text(`[okffs] Refusing to merge ${label}: it targets the protected branch \`${config.protectedBranch}\`. ` +
|
|
56
|
+
"Promotion into the protected branch is a manual, user-driven merge (use promote_branch to open it) — okffs never merges it.");
|
|
57
|
+
}
|
|
58
|
+
if (pr.base.ref !== baseTier) {
|
|
59
|
+
return text(`[okffs] Refusing to merge ${label}: it targets \`${pr.base.ref}\`, not the base tier \`${baseTier}\`. ` +
|
|
60
|
+
"Autonomous merge only lands issue PRs into the base branch.");
|
|
61
|
+
}
|
|
62
|
+
// ── Basic state: open, not draft, not already merged ──────────────────────
|
|
63
|
+
if (pr.merged)
|
|
64
|
+
return text(`${label} is already merged — nothing to do.`);
|
|
65
|
+
if (pr.state !== "open")
|
|
66
|
+
return text(`[okffs] Refusing to merge ${label}: the PR is ${pr.state}, not open.`);
|
|
67
|
+
if (pr.draft)
|
|
68
|
+
return text(`[okffs] Refusing to merge ${label}: it is still a draft. Mark it ready (e.g. create_pull_request finalizes it) first.`);
|
|
69
|
+
// ── Conflicts / needs-update / required-gate signals (mergeable_state) ────
|
|
70
|
+
if (pr.mergeable === false || pr.mergeable_state === "dirty") {
|
|
71
|
+
return text(`[okffs] Refusing to merge ${label}: it has merge conflicts with \`${baseTier}\`. Resolve them, then retry.`);
|
|
72
|
+
}
|
|
73
|
+
if (pr.mergeable_state === "behind") {
|
|
74
|
+
return text(`[okffs] Refusing to merge ${label}: the branch is behind \`${baseTier}\`. Update it (merge/rebase base in), then retry.`);
|
|
75
|
+
}
|
|
76
|
+
if (pr.mergeable_state === "blocked") {
|
|
77
|
+
return text(`[okffs] Refusing to merge ${label}: GitHub reports it as blocked by a required gate (required review or required check not yet satisfied).`);
|
|
78
|
+
}
|
|
79
|
+
if (pr.mergeable === null || pr.mergeable_state === "unknown") {
|
|
80
|
+
return text(`[okffs] Refusing to merge ${label}: GitHub hasn't finished computing its mergeability. Try again shortly.`);
|
|
81
|
+
}
|
|
82
|
+
// ── Gate 4: independently verify checks are green (don't trust the ruleset) ─
|
|
83
|
+
// A ruleset may require NO status checks, yet CI can still be red — so verify
|
|
84
|
+
// the head commit's statuses AND check runs ourselves. Any failing or pending
|
|
85
|
+
// check refuses the merge.
|
|
86
|
+
const [combined, checks] = await Promise.all([
|
|
87
|
+
getCombinedStatus(pr.head.sha),
|
|
88
|
+
getCheckRuns(pr.head.sha),
|
|
89
|
+
]);
|
|
90
|
+
const badStatuses = combined.statuses
|
|
91
|
+
.filter((s) => s.state !== "success")
|
|
92
|
+
.map((s) => `${s.context} (${s.state})`);
|
|
93
|
+
const badChecks = checks.check_runs
|
|
94
|
+
.filter((c) => c.status !== "completed" || !["success", "neutral", "skipped"].includes(c.conclusion ?? ""))
|
|
95
|
+
.map((c) => `${c.name} (${c.status === "completed" ? c.conclusion : c.status})`);
|
|
96
|
+
const failing = [...badStatuses, ...badChecks];
|
|
97
|
+
if (failing.length > 0) {
|
|
98
|
+
return text(`[okffs] Refusing to merge ${label}: not all checks are green. Outstanding: ${failing.join(", ")}. ` +
|
|
99
|
+
"Wait for them to pass (or fix them), then retry.");
|
|
100
|
+
}
|
|
101
|
+
// ── Gate 5: every review thread must be resolved ──────────────────────────
|
|
102
|
+
const review = await getPullRequestReview(pr.number);
|
|
103
|
+
const unresolved = review.threads.filter((t) => !t.isResolved && t.comments.length > 0);
|
|
104
|
+
if (unresolved.length > 0) {
|
|
105
|
+
return text(`[okffs] Refusing to merge ${label}: ${unresolved.length} review thread(s) still unresolved. ` +
|
|
106
|
+
"Address and resolve them (see the address_pr_review prompt), then retry.");
|
|
107
|
+
}
|
|
108
|
+
// ── All gates passed — merge with the base-tier method ────────────────────
|
|
109
|
+
const method = config.baseMergeMethod;
|
|
110
|
+
try {
|
|
111
|
+
await mergePullRequest(pr.number, method);
|
|
112
|
+
}
|
|
113
|
+
catch (err) {
|
|
114
|
+
return text(`[okffs] Merge of ${label} failed at the GitHub API: ${err instanceof Error ? err.message : String(err)}`);
|
|
115
|
+
}
|
|
116
|
+
const lines = [`✅ Merged ${label} into \`${baseTier}\` via ${method}.`];
|
|
117
|
+
// Complete the loop: `Closes #N` only auto-closes when merging into the repo
|
|
118
|
+
// default. For a non-default base tier (e.g. develop) the issue stays open, so
|
|
119
|
+
// close it here. Non-fatal — the merge already succeeded.
|
|
120
|
+
const repoDefault = await getRepoDefaultBranch();
|
|
121
|
+
if (baseTier !== repoDefault) {
|
|
122
|
+
try {
|
|
123
|
+
await closeIssue(input.issue_number);
|
|
124
|
+
lines.push(`Closed #${input.issue_number} (merging into \`${baseTier}\` doesn't trigger GitHub's auto-close).`);
|
|
125
|
+
}
|
|
126
|
+
catch (err) {
|
|
127
|
+
lines.push(`⚠ Could not auto-close #${input.issue_number} — close it manually. (${err instanceof Error ? err.message : String(err)})`);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
lines.push(`GitHub will auto-close #${input.issue_number} via \`Closes #${input.issue_number}\` (merged into the default branch).`);
|
|
132
|
+
}
|
|
133
|
+
// Log the merge on the issue for an audit trail.
|
|
134
|
+
try {
|
|
135
|
+
await addIssueComment(input.issue_number, lines.join("\n"));
|
|
136
|
+
}
|
|
137
|
+
catch {
|
|
138
|
+
/* non-fatal: the response still reports the outcome */
|
|
139
|
+
}
|
|
140
|
+
return text(lines.join("\n"));
|
|
141
|
+
}
|
|
142
|
+
//# sourceMappingURL=merge_pull_request.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"merge_pull_request.js","sourceRoot":"","sources":["../../src/tools/merge_pull_request.ts"],"names":[],"mappings":"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"}
|
package/dist/tools/plan.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
export declare const name = "plan";
|
|
3
|
-
export declare const description = "Plan a piece of work and create all the resulting GitHub issues (with branches, draft PRs when OKFFS_AUTO_PR=true, and board placement when OKFFS_PROJECT_AUTO_ADD=true) in one shot. Given a free-text description of the work, break it down yourself into a structured list of issues \u2014 each with a title, description, inferred labels, an inferred priority/effort where you can judge it, and any relationships between them \u2014 and pass that breakdown as the tasks array. Infer labels from GitHub's defaults: bug, documentation, duplicate, enhancement, good first issue, help wanted, invalid, question, wontfix. Express dependencies via per-task relationships, referencing other tasks by their 1-based position in the list. Two-step confirmation: call once to preview the plan, then re-call with confirmed: true to create everything.";
|
|
3
|
+
export declare const description = "Plan a piece of work and create all the resulting GitHub issues (with branches, draft PRs when OKFFS_AUTO_PR=true, and board placement when OKFFS_PROJECT_AUTO_ADD=true) in one shot. Given a free-text description of the work, break it down yourself into a structured list of issues \u2014 each with a title, description, inferred labels, an inferred priority/effort where you can judge it, an inferred native GitHub Issue Type (Task/Bug/Feature/\u2026 \u2014 commonly Epic for the overall effort and Task/Story/Feature/Bug for its children), and any relationships between them \u2014 and pass that breakdown as the tasks array. Infer labels from GitHub's defaults: bug, documentation, duplicate, enhancement, good first issue, help wanted, invalid, question, wontfix. Express dependencies via per-task relationships, referencing other tasks by their 1-based position in the list. Two-step confirmation: call once to preview the plan, then re-call with confirmed: true to create everything.";
|
|
4
4
|
export declare const inputSchema: z.ZodObject<{
|
|
5
5
|
description: z.ZodString;
|
|
6
6
|
tasks: z.ZodArray<z.ZodObject<{
|
|
@@ -11,6 +11,7 @@ export declare const inputSchema: z.ZodObject<{
|
|
|
11
11
|
milestone: z.ZodOptional<z.ZodNumber>;
|
|
12
12
|
priority: z.ZodOptional<z.ZodString>;
|
|
13
13
|
effort: z.ZodOptional<z.ZodString>;
|
|
14
|
+
type: z.ZodOptional<z.ZodString>;
|
|
14
15
|
relationships: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
15
16
|
type: z.ZodEnum<["blocked_by", "blocking", "parent"]>;
|
|
16
17
|
target: z.ZodNumber;
|
|
@@ -24,6 +25,7 @@ export declare const inputSchema: z.ZodObject<{
|
|
|
24
25
|
}, "strip", z.ZodTypeAny, {
|
|
25
26
|
title: string;
|
|
26
27
|
description: string;
|
|
28
|
+
type?: string | undefined;
|
|
27
29
|
priority?: string | undefined;
|
|
28
30
|
effort?: string | undefined;
|
|
29
31
|
assignees?: string[] | undefined;
|
|
@@ -36,6 +38,7 @@ export declare const inputSchema: z.ZodObject<{
|
|
|
36
38
|
}, {
|
|
37
39
|
title: string;
|
|
38
40
|
description: string;
|
|
41
|
+
type?: string | undefined;
|
|
39
42
|
priority?: string | undefined;
|
|
40
43
|
effort?: string | undefined;
|
|
41
44
|
assignees?: string[] | undefined;
|
|
@@ -52,6 +55,7 @@ export declare const inputSchema: z.ZodObject<{
|
|
|
52
55
|
tasks: {
|
|
53
56
|
title: string;
|
|
54
57
|
description: string;
|
|
58
|
+
type?: string | undefined;
|
|
55
59
|
priority?: string | undefined;
|
|
56
60
|
effort?: string | undefined;
|
|
57
61
|
assignees?: string[] | undefined;
|
|
@@ -68,6 +72,7 @@ export declare const inputSchema: z.ZodObject<{
|
|
|
68
72
|
tasks: {
|
|
69
73
|
title: string;
|
|
70
74
|
description: string;
|
|
75
|
+
type?: string | undefined;
|
|
71
76
|
priority?: string | undefined;
|
|
72
77
|
effort?: string | undefined;
|
|
73
78
|
assignees?: string[] | undefined;
|
package/dist/tools/plan.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plan.d.ts","sourceRoot":"","sources":["../../src/tools/plan.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"plan.d.ts","sourceRoot":"","sources":["../../src/tools/plan.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAuBxB,eAAO,MAAM,IAAI,SAAS,CAAC;AAE3B,eAAO,MAAM,WAAW,i+BACo7B,CAAC;AAoC78B,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAStB,CAAC;AAQH,wBAAsB,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC;;;;;GAyN/D"}
|
package/dist/tools/plan.js
CHANGED
|
@@ -3,8 +3,9 @@ import { createIssue, updateIssueBody, getDefaultBranch, getRef, createBranch, b
|
|
|
3
3
|
import { config } from "../config.js";
|
|
4
4
|
import { git, currentBranch } from "../git.js";
|
|
5
5
|
import { boardAutoAddEnabled, addIssueToBoard, applyInitialStatus, renderBoardLines, } from "../board.js";
|
|
6
|
+
import { applyIssueType } from "../issue_types.js";
|
|
6
7
|
export const name = "plan";
|
|
7
|
-
export const description = "Plan a piece of work and create all the resulting GitHub issues (with branches, draft PRs when OKFFS_AUTO_PR=true, and board placement when OKFFS_PROJECT_AUTO_ADD=true) in one shot. Given a free-text description of the work, break it down yourself into a structured list of issues — each with a title, description, inferred labels, an inferred priority/effort where you can judge it, and any relationships between them — and pass that breakdown as the tasks array. Infer labels from GitHub's defaults: bug, documentation, duplicate, enhancement, good first issue, help wanted, invalid, question, wontfix. Express dependencies via per-task relationships, referencing other tasks by their 1-based position in the list. Two-step confirmation: call once to preview the plan, then re-call with confirmed: true to create everything.";
|
|
8
|
+
export const description = "Plan a piece of work and create all the resulting GitHub issues (with branches, draft PRs when OKFFS_AUTO_PR=true, and board placement when OKFFS_PROJECT_AUTO_ADD=true) in one shot. Given a free-text description of the work, break it down yourself into a structured list of issues — each with a title, description, inferred labels, an inferred priority/effort where you can judge it, an inferred native GitHub Issue Type (Task/Bug/Feature/… — commonly Epic for the overall effort and Task/Story/Feature/Bug for its children), and any relationships between them — and pass that breakdown as the tasks array. Infer labels from GitHub's defaults: bug, documentation, duplicate, enhancement, good first issue, help wanted, invalid, question, wontfix. Express dependencies via per-task relationships, referencing other tasks by their 1-based position in the list. Two-step confirmation: call once to preview the plan, then re-call with confirmed: true to create everything.";
|
|
8
9
|
const relationshipSchema = z.object({
|
|
9
10
|
type: z
|
|
10
11
|
.enum(["blocked_by", "blocking", "parent"])
|
|
@@ -23,6 +24,7 @@ const taskSchema = z.object({
|
|
|
23
24
|
milestone: z.number().int().optional().describe("Milestone number to assign"),
|
|
24
25
|
priority: z.string().optional().describe("Optional Project board Priority (e.g. Urgent, High, Medium, Low). Only applied when OKFFS_PROJECT_AUTO_ADD=true; falls back to OKFFS_DEFAULT_PRIORITY when omitted."),
|
|
25
26
|
effort: z.string().optional().describe("Optional Project board Effort (e.g. High, Medium, Low). Only applied when OKFFS_PROJECT_AUTO_ADD=true; falls back to OKFFS_DEFAULT_EFFORT when omitted."),
|
|
27
|
+
type: z.string().optional().describe("Optional native GitHub Issue Type (e.g. Task, Bug, Feature, Epic, Story) — matched against the org's enabled Issue Types. Skipped cleanly when unavailable; falls back to OKFFS_DEFAULT_TYPE when omitted."),
|
|
26
28
|
relationships: z
|
|
27
29
|
.array(relationshipSchema)
|
|
28
30
|
.optional()
|
|
@@ -78,11 +80,17 @@ export async function handler(input) {
|
|
|
78
80
|
const resolvedLabels = [...new Set([...(task.labels ?? []), ...config.defaultLabels])];
|
|
79
81
|
const resolvedPriority = task.priority ?? config.defaultPriority;
|
|
80
82
|
const resolvedEffort = task.effort ?? config.defaultEffort;
|
|
83
|
+
const resolvedType = task.type ?? config.defaultType;
|
|
81
84
|
const issue = await createIssue(task.title, task.description, resolvedAssignees, resolvedLabels, task.milestone);
|
|
82
85
|
const branchName = buildBranchName(issue.number, task.title);
|
|
83
86
|
await createBranch(branchName, ref.object.sha);
|
|
84
87
|
const body = `${task.description}\n\n**Branch:** \`${branchName}\``;
|
|
85
88
|
await updateIssueBody(issue.number, body);
|
|
89
|
+
// Native Issue Type — non-fatal per task, surfaced in the result below.
|
|
90
|
+
let typeOutcome = null;
|
|
91
|
+
if (resolvedType) {
|
|
92
|
+
typeOutcome = await applyIssueType(issue.number, resolvedType);
|
|
93
|
+
}
|
|
86
94
|
// Add to the board + set Priority/Effort now; the initial Status is applied
|
|
87
95
|
// in a later pass, after any draft PR, so it wins GitHub's linked-PR
|
|
88
96
|
// "In Progress" promotion (#103). Non-fatal and surfaced per issue (#144).
|
|
@@ -105,9 +113,11 @@ export async function handler(input) {
|
|
|
105
113
|
relationships: task.relationships ?? [],
|
|
106
114
|
resolvedPriority,
|
|
107
115
|
resolvedEffort,
|
|
116
|
+
resolvedType,
|
|
108
117
|
boardAdd,
|
|
109
118
|
boardError,
|
|
110
119
|
initialStatus: null,
|
|
120
|
+
typeOutcome,
|
|
111
121
|
});
|
|
112
122
|
}
|
|
113
123
|
// Second pass: resolve relationship targets (1-based task indices) to issue
|
|
@@ -187,6 +197,11 @@ export async function handler(input) {
|
|
|
187
197
|
initialStatus: entry.initialStatus,
|
|
188
198
|
indent: " ",
|
|
189
199
|
}));
|
|
200
|
+
if (entry.typeOutcome) {
|
|
201
|
+
lines.push("applied" in entry.typeOutcome
|
|
202
|
+
? ` Type: ${entry.typeOutcome.applied}`
|
|
203
|
+
: ` ⚠ Type "${entry.resolvedType}" not set — ${entry.typeOutcome.skipped}`);
|
|
204
|
+
}
|
|
190
205
|
return lines.join("\n");
|
|
191
206
|
});
|
|
192
207
|
return {
|
package/dist/tools/plan.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plan.js","sourceRoot":"","sources":["../../src/tools/plan.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EACL,WAAW,EACX,eAAe,EACf,gBAAgB,EAChB,MAAM,EACN,YAAY,EACZ,eAAe,EACf,sBAAsB,GACvB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,GAAG,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC/C,OAAO,EACL,mBAAmB,EACnB,eAAe,EACf,kBAAkB,EAClB,gBAAgB,
|
|
1
|
+
{"version":3,"file":"plan.js","sourceRoot":"","sources":["../../src/tools/plan.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,12 +5,15 @@ export declare const inputSchema: z.ZodObject<{
|
|
|
5
5
|
issue_number: z.ZodNumber;
|
|
6
6
|
priority: z.ZodOptional<z.ZodString>;
|
|
7
7
|
effort: z.ZodOptional<z.ZodString>;
|
|
8
|
+
type: z.ZodOptional<z.ZodString>;
|
|
8
9
|
}, "strip", z.ZodTypeAny, {
|
|
9
10
|
issue_number: number;
|
|
11
|
+
type?: string | undefined;
|
|
10
12
|
priority?: string | undefined;
|
|
11
13
|
effort?: string | undefined;
|
|
12
14
|
}, {
|
|
13
15
|
issue_number: number;
|
|
16
|
+
type?: string | undefined;
|
|
14
17
|
priority?: string | undefined;
|
|
15
18
|
effort?: string | undefined;
|
|
16
19
|
}>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"set_issue_fields.d.ts","sourceRoot":"","sources":["../../src/tools/set_issue_fields.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"set_issue_fields.d.ts","sourceRoot":"","sources":["../../src/tools/set_issue_fields.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAMxB,eAAO,MAAM,IAAI,qBAAqB,CAAC;AAEvC,eAAO,MAAM,WAAW,QAKyG,CAAC;AAElI,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;EAKtB,CAAC;AASH,wBAAsB,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC;;;;;GAiC/D"}
|
|
@@ -2,47 +2,55 @@ import { z } from "zod";
|
|
|
2
2
|
import { getIssue } from "../github.js";
|
|
3
3
|
import { config } from "../config.js";
|
|
4
4
|
import { addIssueToBoard } from "../board.js";
|
|
5
|
+
import { applyIssueType } from "../issue_types.js";
|
|
5
6
|
export const name = "set_issue_fields";
|
|
6
|
-
export const description = "Set
|
|
7
|
-
"Use this to set
|
|
8
|
-
"
|
|
9
|
-
"
|
|
7
|
+
export const description = "Set enumerated fields on an EXISTING issue: the GitHub Projects v2 board Priority and/or Effort, and/or the native GitHub Issue Type (Task/Bug/Feature/…). " +
|
|
8
|
+
"Use this to set these on issues that already exist — create_issue only sets them at creation time. " +
|
|
9
|
+
"Priority/Effort handle both project-native single-select fields and org-level Issue Fields (the latter needs OKFFS_CLASSIC_PAT + a classic admin:org PAT) and require OKFFS_PROJECT_ENABLED. " +
|
|
10
|
+
"Type is a native GitHub Issue Type (org-level; skipped cleanly on user repos / when unavailable) and works independently of the board. " +
|
|
11
|
+
"To move an issue's Status column, use update_project_status; to edit title/assignees/labels/milestone/body, use update_issue.";
|
|
10
12
|
export const inputSchema = z.object({
|
|
11
13
|
issue_number: z.number().int().positive().describe("The issue number to set fields on"),
|
|
12
|
-
priority: z.string().optional().describe("Board Priority to set (e.g. Urgent, High, Medium, Low) — matched against the board's Priority options"),
|
|
13
|
-
effort: z.string().optional().describe("Board Effort to set (e.g. High, Medium, Low) — matched against the board's Effort options"),
|
|
14
|
+
priority: z.string().optional().describe("Board Priority to set (e.g. Urgent, High, Medium, Low) — matched against the board's Priority options. Requires OKFFS_PROJECT_ENABLED."),
|
|
15
|
+
effort: z.string().optional().describe("Board Effort to set (e.g. High, Medium, Low) — matched against the board's Effort options. Requires OKFFS_PROJECT_ENABLED."),
|
|
16
|
+
type: z.string().optional().describe("Native GitHub Issue Type to set (e.g. Task, Bug, Feature, Epic, Story) — matched against the org's enabled Issue Types. Independent of the board."),
|
|
14
17
|
});
|
|
15
18
|
const text = (t) => ({ content: [{ type: "text", text: t }] });
|
|
19
|
+
const renderOutcome = (label, requested, outcome) => "applied" in outcome
|
|
20
|
+
? `${label} → ${outcome.applied}`
|
|
21
|
+
: `⚠ ${label} "${requested}" not set — ${outcome.skipped}`;
|
|
16
22
|
export async function handler(input) {
|
|
17
|
-
if (!
|
|
18
|
-
return text("
|
|
19
|
-
}
|
|
20
|
-
if (!input.priority && !input.effort) {
|
|
21
|
-
return text("Nothing to set — pass a priority and/or an effort. (For the Status column, use update_project_status.)");
|
|
22
|
-
}
|
|
23
|
-
const issue = await getIssue(input.issue_number);
|
|
24
|
-
let result;
|
|
25
|
-
try {
|
|
26
|
-
// addIssueToBoard adds the issue to the board (idempotent — returns the
|
|
27
|
-
// existing item if already present) and sets Priority/Effort via the shared,
|
|
28
|
-
// org-Issue-Field-aware path. Reused so existing issues get identical handling
|
|
29
|
-
// and surfacing to create_issue.
|
|
30
|
-
result = await addIssueToBoard(issue.node_id, { priority: input.priority, effort: input.effort });
|
|
31
|
-
}
|
|
32
|
-
catch (err) {
|
|
33
|
-
return text(`[okffs] Failed to update board fields on #${input.issue_number}: ${err instanceof Error ? err.message : String(err)}`);
|
|
23
|
+
if (!input.priority && !input.effort && !input.type) {
|
|
24
|
+
return text("Nothing to set — pass a priority, effort, and/or type. (Status column → update_project_status; title/assignees/labels/milestone/body → update_issue.)");
|
|
34
25
|
}
|
|
35
26
|
const lines = [];
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
27
|
+
// Board fields (Priority/Effort) — gated on the Projects integration.
|
|
28
|
+
if (input.priority || input.effort) {
|
|
29
|
+
if (!config.projectEnabled) {
|
|
30
|
+
lines.push("⚠ Priority/Effort not set — OKFFS_PROJECT_ENABLED is not set, so board field updates are disabled.");
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
const issue = await getIssue(input.issue_number);
|
|
34
|
+
try {
|
|
35
|
+
// addIssueToBoard adds the issue to the board (idempotent) and sets
|
|
36
|
+
// Priority/Effort via the shared, org-Issue-Field-aware path — identical
|
|
37
|
+
// handling and surfacing to create_issue.
|
|
38
|
+
const result = await addIssueToBoard(issue.node_id, { priority: input.priority, effort: input.effort });
|
|
39
|
+
if (result.priority)
|
|
40
|
+
lines.push(renderOutcome("Priority", input.priority, result.priority));
|
|
41
|
+
if (result.effort)
|
|
42
|
+
lines.push(renderOutcome("Effort", input.effort, result.effort));
|
|
43
|
+
}
|
|
44
|
+
catch (err) {
|
|
45
|
+
lines.push(`⚠ Failed to update board fields: ${err instanceof Error ? err.message : String(err)}`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
40
48
|
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
49
|
+
// Native Issue Type — org-level, independent of the board. Non-fatal.
|
|
50
|
+
if (input.type) {
|
|
51
|
+
const outcome = await applyIssueType(input.issue_number, input.type);
|
|
52
|
+
lines.push(renderOutcome("Type", input.type, outcome));
|
|
45
53
|
}
|
|
46
|
-
return text(`Issue #${input.issue_number}
|
|
54
|
+
return text(`Issue #${input.issue_number} fields:\n${lines.map((l) => ` ${l}`).join("\n")}`);
|
|
47
55
|
}
|
|
48
56
|
//# sourceMappingURL=set_issue_fields.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"set_issue_fields.js","sourceRoot":"","sources":["../../src/tools/set_issue_fields.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,eAAe,
|
|
1
|
+
{"version":3,"file":"set_issue_fields.js","sourceRoot":"","sources":["../../src/tools/set_issue_fields.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const name = "update_issue";
|
|
3
|
+
export declare const description: string;
|
|
4
|
+
export declare const inputSchema: z.ZodObject<{
|
|
5
|
+
issue_number: z.ZodNumber;
|
|
6
|
+
title: z.ZodOptional<z.ZodString>;
|
|
7
|
+
body: z.ZodOptional<z.ZodString>;
|
|
8
|
+
assignees: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
9
|
+
labels: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
10
|
+
milestone: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
11
|
+
}, "strip", z.ZodTypeAny, {
|
|
12
|
+
issue_number: number;
|
|
13
|
+
title?: string | undefined;
|
|
14
|
+
body?: string | undefined;
|
|
15
|
+
assignees?: string[] | undefined;
|
|
16
|
+
labels?: string[] | undefined;
|
|
17
|
+
milestone?: number | null | undefined;
|
|
18
|
+
}, {
|
|
19
|
+
issue_number: number;
|
|
20
|
+
title?: string | undefined;
|
|
21
|
+
body?: string | undefined;
|
|
22
|
+
assignees?: string[] | undefined;
|
|
23
|
+
labels?: string[] | undefined;
|
|
24
|
+
milestone?: number | null | undefined;
|
|
25
|
+
}>;
|
|
26
|
+
export declare function handler(input: z.infer<typeof inputSchema>): Promise<{
|
|
27
|
+
content: {
|
|
28
|
+
type: "text";
|
|
29
|
+
text: string;
|
|
30
|
+
}[];
|
|
31
|
+
}>;
|
|
32
|
+
//# sourceMappingURL=update_issue.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"update_issue.d.ts","sourceRoot":"","sources":["../../src/tools/update_issue.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,IAAI,iBAAiB,CAAC;AAEnC,eAAO,MAAM,WAAW,QAQ0C,CAAC;AAEnE,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;EAOtB,CAAC;AAIH,wBAAsB,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC;;;;;GA+B/D"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { updateIssue } from "../github.js";
|
|
3
|
+
export const name = "update_issue";
|
|
4
|
+
export const description = "Mutate the core fields of an EXISTING GitHub issue — title, assignees, labels, milestone, and/or body. " +
|
|
5
|
+
"create_issue only sets these at creation time; this is how you change them afterward (e.g. rename an issue, " +
|
|
6
|
+
"add or change an assignee) without dropping to raw `gh issue edit`. Authenticates with okffs's configured token " +
|
|
7
|
+
"(GITHUB_TOKEN, or the gh CLI fallback when it's unset) and applies okffs conventions. Pass only the fields you " +
|
|
8
|
+
"want to change — omitted fields are left untouched. NOTE: labels and assignees REPLACE the whole set (they do " +
|
|
9
|
+
"not merge with the current values), so pass the complete desired list; an empty array [] clears them, and " +
|
|
10
|
+
"milestone: null clears the milestone. For board Priority/Effort use set_issue_fields, and for the board Status " +
|
|
11
|
+
"column use update_project_status — those are not issue fields.";
|
|
12
|
+
export const inputSchema = z.object({
|
|
13
|
+
issue_number: z.number().int().positive().describe("The issue number to update"),
|
|
14
|
+
title: z.string().optional().describe("New issue title"),
|
|
15
|
+
body: z.string().optional().describe("New issue body. Replaces the existing body — pass the full content, not a fragment."),
|
|
16
|
+
assignees: z.array(z.string()).optional().describe("GitHub usernames to assign. REPLACES the current assignees (not merged); [] clears them."),
|
|
17
|
+
labels: z.array(z.string()).optional().describe("Labels to apply. REPLACES the current labels (not merged); [] clears them."),
|
|
18
|
+
milestone: z.number().int().positive().nullable().optional().describe("Milestone number to assign, or null to clear the milestone."),
|
|
19
|
+
});
|
|
20
|
+
const text = (t) => ({ content: [{ type: "text", text: t }] });
|
|
21
|
+
export async function handler(input) {
|
|
22
|
+
const { issue_number, ...fields } = input;
|
|
23
|
+
// Require at least one field to change — mirrors set_issue_fields' guard so a
|
|
24
|
+
// no-op call gives an actionable message instead of a silent PATCH.
|
|
25
|
+
const provided = ["title", "body", "assignees", "labels", "milestone"].filter((k) => fields[k] !== undefined);
|
|
26
|
+
if (provided.length === 0) {
|
|
27
|
+
return text("Nothing to update — pass at least one of: title, body, assignees, labels, milestone. " +
|
|
28
|
+
"(For board Priority/Effort use set_issue_fields; for the Status column use update_project_status.)");
|
|
29
|
+
}
|
|
30
|
+
let updated;
|
|
31
|
+
try {
|
|
32
|
+
updated = await updateIssue(issue_number, fields);
|
|
33
|
+
}
|
|
34
|
+
catch (err) {
|
|
35
|
+
return text(`[okffs] Failed to update issue #${issue_number}: ${err instanceof Error ? err.message : String(err)}`);
|
|
36
|
+
}
|
|
37
|
+
const lines = provided.map((k) => {
|
|
38
|
+
const v = fields[k];
|
|
39
|
+
const shown = Array.isArray(v)
|
|
40
|
+
? (v.length ? v.join(", ") : "(cleared)")
|
|
41
|
+
: v === null ? "(cleared)" : String(v);
|
|
42
|
+
return ` ${k} → ${shown}`;
|
|
43
|
+
});
|
|
44
|
+
return text(`Issue #${issue_number} updated:\n${lines.join("\n")}\n${updated.html_url}`);
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=update_issue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"update_issue.js","sourceRoot":"","sources":["../../src/tools/update_issue.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@neturely/okffs",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"mcpName": "io.github.neturely/okffs",
|
|
5
5
|
"description": "MCP server that connects Claude Code to GitHub — create and manage issues and branches without leaving your editor.",
|
|
6
6
|
"type": "module",
|