maxsimcli 4.8.0 → 4.10.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/README.md +180 -202
- package/dist/assets/CHANGELOG.md +61 -0
- package/dist/assets/hooks/maxsim-check-update.cjs +38 -0
- package/dist/assets/hooks/maxsim-check-update.cjs.map +1 -1
- package/dist/assets/hooks/maxsim-statusline.cjs +116 -48
- package/dist/assets/hooks/maxsim-statusline.cjs.map +1 -1
- package/dist/assets/hooks/maxsim-sync-reminder.cjs +117 -0
- package/dist/assets/hooks/maxsim-sync-reminder.cjs.map +1 -0
- package/dist/assets/templates/agents/AGENTS.md +78 -106
- package/dist/assets/templates/agents/executor.md +101 -0
- package/dist/assets/templates/agents/planner.md +86 -0
- package/dist/assets/templates/agents/researcher.md +71 -0
- package/dist/assets/templates/agents/verifier.md +88 -0
- package/dist/assets/templates/commands/maxsim/debug.md +7 -7
- package/dist/assets/templates/commands/maxsim/execute.md +45 -0
- package/dist/assets/templates/commands/maxsim/go.md +29 -0
- package/dist/assets/templates/commands/maxsim/help.md +2 -2
- package/dist/assets/templates/commands/maxsim/init.md +52 -0
- package/dist/assets/templates/commands/maxsim/plan.md +50 -0
- package/dist/assets/templates/commands/maxsim/progress.md +4 -3
- package/dist/assets/templates/commands/maxsim/quick.md +6 -4
- package/dist/assets/templates/commands/maxsim/settings.md +4 -3
- package/dist/assets/templates/references/continuation-format.md +16 -16
- package/dist/assets/templates/references/model-profile-resolution.md +1 -1
- package/dist/assets/templates/references/model-profiles.md +12 -19
- package/dist/assets/templates/rules/conventions.md +51 -0
- package/dist/assets/templates/rules/verification-protocol.md +57 -0
- package/dist/assets/templates/skills/agent-system-map/SKILL.md +92 -0
- package/dist/assets/templates/skills/brainstorming/SKILL.md +48 -36
- package/dist/assets/templates/skills/code-review/SKILL.md +40 -61
- package/dist/assets/templates/skills/commit-conventions/SKILL.md +75 -0
- package/dist/assets/templates/skills/evidence-collection/SKILL.md +87 -0
- package/dist/assets/templates/skills/handoff-contract/SKILL.md +70 -0
- package/dist/assets/templates/skills/input-validation/SKILL.md +51 -0
- package/dist/assets/templates/skills/maxsim-batch/SKILL.md +41 -45
- package/dist/assets/templates/skills/maxsim-simplify/SKILL.md +37 -90
- package/dist/assets/templates/skills/memory-management/SKILL.md +32 -67
- package/dist/assets/templates/skills/research-methodology/SKILL.md +137 -0
- package/dist/assets/templates/skills/roadmap-writing/SKILL.md +40 -58
- package/dist/assets/templates/skills/sdd/SKILL.md +34 -69
- package/dist/assets/templates/skills/systematic-debugging/SKILL.md +20 -26
- package/dist/assets/templates/skills/tdd/SKILL.md +25 -33
- package/dist/assets/templates/skills/tool-priority-guide/SKILL.md +80 -0
- package/dist/assets/templates/skills/using-maxsim/SKILL.md +42 -73
- package/dist/assets/templates/skills/verification-before-completion/SKILL.md +12 -24
- package/dist/assets/templates/skills/verification-gates/SKILL.md +169 -0
- package/dist/assets/templates/templates/UAT.md +3 -3
- package/dist/assets/templates/templates/VALIDATION.md +1 -1
- package/dist/assets/templates/templates/context.md +4 -4
- package/dist/assets/templates/templates/debug-subagent-prompt.md +3 -3
- package/dist/assets/templates/templates/discovery.md +2 -2
- package/dist/assets/templates/templates/phase-prompt.md +2 -2
- package/dist/assets/templates/templates/planner-subagent-prompt.md +7 -7
- package/dist/assets/templates/templates/project.md +1 -1
- package/dist/assets/templates/templates/research.md +1 -1
- package/dist/assets/templates/templates/state.md +2 -2
- package/dist/assets/templates/templates/summary.md +41 -0
- package/dist/assets/templates/workflows/batch.md +5 -5
- package/dist/assets/templates/workflows/diagnose-issues.md +2 -2
- package/dist/assets/templates/workflows/discovery-phase.md +3 -3
- package/dist/assets/templates/workflows/discuss-phase.md +11 -11
- package/dist/assets/templates/workflows/execute-phase.md +205 -11
- package/dist/assets/templates/workflows/execute-plan.md +299 -34
- package/dist/assets/templates/workflows/execute.md +421 -0
- package/dist/assets/templates/workflows/go.md +250 -0
- package/dist/assets/templates/workflows/health.md +5 -5
- package/dist/assets/templates/workflows/help.md +165 -435
- package/dist/assets/templates/workflows/init-existing.md +23 -23
- package/dist/assets/templates/workflows/init.md +205 -0
- package/dist/assets/templates/workflows/new-milestone.md +9 -9
- package/dist/assets/templates/workflows/new-project.md +26 -26
- package/dist/assets/templates/workflows/plan-create.md +298 -0
- package/dist/assets/templates/workflows/plan-discuss.md +347 -0
- package/dist/assets/templates/workflows/plan-phase.md +29 -29
- package/dist/assets/templates/workflows/plan-research.md +177 -0
- package/dist/assets/templates/workflows/plan.md +231 -0
- package/dist/assets/templates/workflows/progress.md +46 -42
- package/dist/assets/templates/workflows/quick.md +195 -14
- package/dist/assets/templates/workflows/research-phase.md +5 -5
- package/dist/assets/templates/workflows/sdd.md +20 -12
- package/dist/assets/templates/workflows/settings.md +18 -14
- package/dist/assets/templates/workflows/verify-phase.md +1 -1
- package/dist/assets/templates/workflows/verify-work.md +16 -16
- package/dist/cli.cjs +4589 -229
- package/dist/cli.cjs.map +1 -1
- package/dist/core-D5zUr9cb.cjs.map +1 -1
- package/dist/install.cjs +234 -17
- package/dist/install.cjs.map +1 -1
- package/dist/mcp-server.cjs +298 -20
- package/dist/mcp-server.cjs.map +1 -1
- package/dist/skills-CjFWZIGM.cjs.map +1 -1
- package/package.json +1 -1
- package/dist/assets/hooks/maxsim-context-monitor.cjs +0 -121
- package/dist/assets/hooks/maxsim-context-monitor.cjs.map +0 -1
- package/dist/assets/templates/agents/maxsim-code-reviewer.md +0 -239
- package/dist/assets/templates/agents/maxsim-codebase-mapper.md +0 -214
- package/dist/assets/templates/agents/maxsim-debugger.md +0 -572
- package/dist/assets/templates/agents/maxsim-drift-checker.md +0 -522
- package/dist/assets/templates/agents/maxsim-executor.md +0 -504
- package/dist/assets/templates/agents/maxsim-integration-checker.md +0 -273
- package/dist/assets/templates/agents/maxsim-phase-researcher.md +0 -305
- package/dist/assets/templates/agents/maxsim-plan-checker.md +0 -343
- package/dist/assets/templates/agents/maxsim-planner.md +0 -610
- package/dist/assets/templates/agents/maxsim-project-researcher.md +0 -359
- package/dist/assets/templates/agents/maxsim-research-synthesizer.md +0 -263
- package/dist/assets/templates/agents/maxsim-roadmapper.md +0 -324
- package/dist/assets/templates/agents/maxsim-spec-reviewer.md +0 -245
- package/dist/assets/templates/agents/maxsim-verifier.md +0 -393
- package/dist/assets/templates/commands/maxsim/add-phase.md +0 -43
- package/dist/assets/templates/commands/maxsim/add-tests.md +0 -41
- package/dist/assets/templates/commands/maxsim/add-todo.md +0 -57
- package/dist/assets/templates/commands/maxsim/artefakte.md +0 -122
- package/dist/assets/templates/commands/maxsim/audit-milestone.md +0 -36
- package/dist/assets/templates/commands/maxsim/batch.md +0 -42
- package/dist/assets/templates/commands/maxsim/check-drift.md +0 -56
- package/dist/assets/templates/commands/maxsim/check-todos.md +0 -46
- package/dist/assets/templates/commands/maxsim/cleanup.md +0 -18
- package/dist/assets/templates/commands/maxsim/complete-milestone.md +0 -136
- package/dist/assets/templates/commands/maxsim/discuss-phase.md +0 -87
- package/dist/assets/templates/commands/maxsim/discuss.md +0 -70
- package/dist/assets/templates/commands/maxsim/execute-phase.md +0 -41
- package/dist/assets/templates/commands/maxsim/health.md +0 -22
- package/dist/assets/templates/commands/maxsim/init-existing.md +0 -46
- package/dist/assets/templates/commands/maxsim/insert-phase.md +0 -32
- package/dist/assets/templates/commands/maxsim/list-phase-assumptions.md +0 -46
- package/dist/assets/templates/commands/maxsim/map-codebase.md +0 -71
- package/dist/assets/templates/commands/maxsim/new-milestone.md +0 -44
- package/dist/assets/templates/commands/maxsim/new-project.md +0 -46
- package/dist/assets/templates/commands/maxsim/pause-work.md +0 -38
- package/dist/assets/templates/commands/maxsim/plan-milestone-gaps.md +0 -34
- package/dist/assets/templates/commands/maxsim/plan-phase.md +0 -44
- package/dist/assets/templates/commands/maxsim/realign.md +0 -39
- package/dist/assets/templates/commands/maxsim/reapply-patches.md +0 -110
- package/dist/assets/templates/commands/maxsim/remove-phase.md +0 -31
- package/dist/assets/templates/commands/maxsim/research-phase.md +0 -189
- package/dist/assets/templates/commands/maxsim/resume-work.md +0 -40
- package/dist/assets/templates/commands/maxsim/roadmap.md +0 -19
- package/dist/assets/templates/commands/maxsim/sdd.md +0 -39
- package/dist/assets/templates/commands/maxsim/set-profile.md +0 -34
- package/dist/assets/templates/commands/maxsim/update.md +0 -37
- package/dist/assets/templates/commands/maxsim/verify-work.md +0 -38
- package/dist/assets/templates/workflows/add-phase.md +0 -111
- package/dist/assets/templates/workflows/add-tests.md +0 -351
- package/dist/assets/templates/workflows/add-todo.md +0 -247
- package/dist/assets/templates/workflows/audit-milestone.md +0 -297
- package/dist/assets/templates/workflows/check-drift.md +0 -248
- package/dist/assets/templates/workflows/check-todos.md +0 -261
- package/dist/assets/templates/workflows/cleanup.md +0 -153
- package/dist/assets/templates/workflows/complete-milestone.md +0 -701
- package/dist/assets/templates/workflows/discuss.md +0 -343
- package/dist/assets/templates/workflows/insert-phase.md +0 -129
- package/dist/assets/templates/workflows/list-phase-assumptions.md +0 -178
- package/dist/assets/templates/workflows/map-codebase.md +0 -315
- package/dist/assets/templates/workflows/pause-work.md +0 -122
- package/dist/assets/templates/workflows/plan-milestone-gaps.md +0 -274
- package/dist/assets/templates/workflows/realign.md +0 -288
- package/dist/assets/templates/workflows/remove-phase.md +0 -154
- package/dist/assets/templates/workflows/resume-project.md +0 -306
- package/dist/assets/templates/workflows/roadmap.md +0 -130
- package/dist/assets/templates/workflows/set-profile.md +0 -81
- package/dist/assets/templates/workflows/transition.md +0 -544
- package/dist/assets/templates/workflows/update.md +0 -220
package/dist/mcp-server.cjs
CHANGED
|
@@ -39,6 +39,7 @@ let child_process = require("child_process");
|
|
|
39
39
|
require("node:events");
|
|
40
40
|
let node_child_process = require("node:child_process");
|
|
41
41
|
let node_util = require("node:util");
|
|
42
|
+
let node_crypto = require("node:crypto");
|
|
42
43
|
|
|
43
44
|
//#region ../../node_modules/zod/v3/helpers/util.js
|
|
44
45
|
var util$2;
|
|
@@ -26858,6 +26859,12 @@ async function pathExistsInternal(p) {
|
|
|
26858
26859
|
async function loadConfig(cwd) {
|
|
26859
26860
|
if (_configCache && _configCache.cwd === cwd) return _configCache.config;
|
|
26860
26861
|
const cfgPath = configPath(cwd);
|
|
26862
|
+
const reviewDefaults = {
|
|
26863
|
+
spec_review: true,
|
|
26864
|
+
code_review: true,
|
|
26865
|
+
simplify_review: true,
|
|
26866
|
+
retry_limit: 3
|
|
26867
|
+
};
|
|
26861
26868
|
const defaults = {
|
|
26862
26869
|
model_profile: "balanced",
|
|
26863
26870
|
commit_docs: true,
|
|
@@ -26869,7 +26876,10 @@ async function loadConfig(cwd) {
|
|
|
26869
26876
|
plan_checker: true,
|
|
26870
26877
|
verifier: true,
|
|
26871
26878
|
parallelization: true,
|
|
26872
|
-
brave_search: false
|
|
26879
|
+
brave_search: false,
|
|
26880
|
+
worktree_mode: "auto",
|
|
26881
|
+
max_parallel_agents: 10,
|
|
26882
|
+
review: reviewDefaults
|
|
26873
26883
|
};
|
|
26874
26884
|
try {
|
|
26875
26885
|
const raw = await node_fs.promises.readFile(cfgPath, "utf-8");
|
|
@@ -26926,7 +26936,17 @@ async function loadConfig(cwd) {
|
|
|
26926
26936
|
}) ?? defaults.verifier,
|
|
26927
26937
|
parallelization,
|
|
26928
26938
|
brave_search: get("brave_search") ?? defaults.brave_search,
|
|
26929
|
-
model_overrides: parsed["model_overrides"]
|
|
26939
|
+
model_overrides: parsed["model_overrides"],
|
|
26940
|
+
worktree_mode: get("worktree_mode") ?? defaults.worktree_mode,
|
|
26941
|
+
max_parallel_agents: get("max_parallel_agents") ?? defaults.max_parallel_agents,
|
|
26942
|
+
review: (() => {
|
|
26943
|
+
const userReview = get("review");
|
|
26944
|
+
if (!userReview || typeof userReview !== "object") return reviewDefaults;
|
|
26945
|
+
return {
|
|
26946
|
+
...reviewDefaults,
|
|
26947
|
+
...userReview
|
|
26948
|
+
};
|
|
26949
|
+
})()
|
|
26930
26950
|
};
|
|
26931
26951
|
_configCache = {
|
|
26932
26952
|
cwd,
|
|
@@ -38040,9 +38060,9 @@ async function postPlanComment(phaseIssueNumber, planNumber, planContent) {
|
|
|
38040
38060
|
/**
|
|
38041
38061
|
* Close an issue. Optionally post a reason comment before closing.
|
|
38042
38062
|
*
|
|
38043
|
-
*
|
|
38063
|
+
* @param stateReason - 'completed' (default) or 'not_planned' (rollback/cancel)
|
|
38044
38064
|
*/
|
|
38045
|
-
async function closeIssue(issueNumber, reason) {
|
|
38065
|
+
async function closeIssue(issueNumber, reason, stateReason = "completed") {
|
|
38046
38066
|
return withGhResult(async () => {
|
|
38047
38067
|
const octokit = getOctokit();
|
|
38048
38068
|
const { owner, repo } = await getRepoInfo();
|
|
@@ -38057,7 +38077,7 @@ async function closeIssue(issueNumber, reason) {
|
|
|
38057
38077
|
repo,
|
|
38058
38078
|
issue_number: issueNumber,
|
|
38059
38079
|
state: "closed",
|
|
38060
|
-
state_reason:
|
|
38080
|
+
state_reason: stateReason
|
|
38061
38081
|
});
|
|
38062
38082
|
});
|
|
38063
38083
|
}
|
|
@@ -38079,7 +38099,7 @@ async function reopenIssue(issueNumber) {
|
|
|
38079
38099
|
/**
|
|
38080
38100
|
* Fetch a single issue by number.
|
|
38081
38101
|
*
|
|
38082
|
-
* Returns number, id, title, state, and
|
|
38102
|
+
* Returns number, id, title, state, body, updated_at, labels, and comments_url.
|
|
38083
38103
|
*/
|
|
38084
38104
|
async function getPhaseIssue(phaseIssueNumber) {
|
|
38085
38105
|
return withGhResult(async () => {
|
|
@@ -38090,12 +38110,16 @@ async function getPhaseIssue(phaseIssueNumber) {
|
|
|
38090
38110
|
repo,
|
|
38091
38111
|
issue_number: phaseIssueNumber
|
|
38092
38112
|
});
|
|
38113
|
+
const labels = response.data.labels.map((l) => typeof l === "string" ? l : l.name ?? "").filter(Boolean);
|
|
38093
38114
|
return {
|
|
38094
38115
|
number: response.data.number,
|
|
38095
38116
|
id: response.data.id,
|
|
38096
38117
|
title: response.data.title,
|
|
38097
38118
|
state: response.data.state,
|
|
38098
|
-
body: response.data.body ?? ""
|
|
38119
|
+
body: response.data.body ?? "",
|
|
38120
|
+
updated_at: response.data.updated_at,
|
|
38121
|
+
labels,
|
|
38122
|
+
comments_url: response.data.comments_url
|
|
38099
38123
|
};
|
|
38100
38124
|
});
|
|
38101
38125
|
}
|
|
@@ -38103,7 +38127,7 @@ async function getPhaseIssue(phaseIssueNumber) {
|
|
|
38103
38127
|
* List all sub-issues of a phase Issue.
|
|
38104
38128
|
*
|
|
38105
38129
|
* Uses GitHub's native sub-issues API.
|
|
38106
|
-
* Returns each sub-issue's number, id, title, and
|
|
38130
|
+
* Returns each sub-issue's number, id, title, state, and updated_at.
|
|
38107
38131
|
*/
|
|
38108
38132
|
async function listPhaseSubIssues(phaseIssueNumber) {
|
|
38109
38133
|
return withGhResult(async () => {
|
|
@@ -38117,7 +38141,8 @@ async function listPhaseSubIssues(phaseIssueNumber) {
|
|
|
38117
38141
|
number: issue.number,
|
|
38118
38142
|
id: issue.id,
|
|
38119
38143
|
title: issue.title,
|
|
38120
|
-
state: issue.state
|
|
38144
|
+
state: issue.state,
|
|
38145
|
+
updated_at: issue.updated_at ?? ""
|
|
38121
38146
|
}));
|
|
38122
38147
|
});
|
|
38123
38148
|
}
|
|
@@ -38239,6 +38264,13 @@ function mappingFilePath(cwd) {
|
|
|
38239
38264
|
return planningPath(cwd, MAPPING_FILENAME);
|
|
38240
38265
|
}
|
|
38241
38266
|
/**
|
|
38267
|
+
* Compute a SHA-256 hash of an issue body string.
|
|
38268
|
+
* Used for external edit detection (WIRE-06).
|
|
38269
|
+
*/
|
|
38270
|
+
function hashBody(body) {
|
|
38271
|
+
return (0, node_crypto.createHash)("sha256").update(body).digest("hex");
|
|
38272
|
+
}
|
|
38273
|
+
/**
|
|
38242
38274
|
* Load and parse the mapping file (local cache).
|
|
38243
38275
|
*
|
|
38244
38276
|
* Returns null if the file does not exist.
|
|
@@ -38268,6 +38300,39 @@ function saveMapping(cwd, mapping) {
|
|
|
38268
38300
|
node_fs.default.mkdirSync(dir, { recursive: true });
|
|
38269
38301
|
node_fs.default.writeFileSync(filePath, JSON.stringify(mapping, null, 2) + "\n", "utf-8");
|
|
38270
38302
|
}
|
|
38303
|
+
/**
|
|
38304
|
+
* Update a specific task's issue mapping within a phase.
|
|
38305
|
+
*
|
|
38306
|
+
* Load-modify-save pattern. Creates phase entry if it does not exist.
|
|
38307
|
+
* Merges partial data with existing entry (if any).
|
|
38308
|
+
*
|
|
38309
|
+
* @throws If mapping file does not exist (must be initialized first via saveMapping)
|
|
38310
|
+
*/
|
|
38311
|
+
function updateTaskMapping(cwd, phaseNum, taskId, data) {
|
|
38312
|
+
const mapping = loadMapping(cwd);
|
|
38313
|
+
if (!mapping) throw new Error("github-issues.json does not exist. Run project setup first.");
|
|
38314
|
+
if (!mapping.phases[phaseNum]) mapping.phases[phaseNum] = {
|
|
38315
|
+
tracking_issue: {
|
|
38316
|
+
number: 0,
|
|
38317
|
+
id: 0,
|
|
38318
|
+
node_id: "",
|
|
38319
|
+
item_id: "",
|
|
38320
|
+
status: "To Do"
|
|
38321
|
+
},
|
|
38322
|
+
plan: "",
|
|
38323
|
+
tasks: {}
|
|
38324
|
+
};
|
|
38325
|
+
const existing = mapping.phases[phaseNum].tasks[taskId];
|
|
38326
|
+
const defaults = {
|
|
38327
|
+
number: 0,
|
|
38328
|
+
id: 0,
|
|
38329
|
+
node_id: "",
|
|
38330
|
+
item_id: "",
|
|
38331
|
+
status: "To Do"
|
|
38332
|
+
};
|
|
38333
|
+
mapping.phases[phaseNum].tasks[taskId] = Object.assign(defaults, existing, data);
|
|
38334
|
+
saveMapping(cwd, mapping);
|
|
38335
|
+
}
|
|
38271
38336
|
|
|
38272
38337
|
//#endregion
|
|
38273
38338
|
//#region src/mcp/utils.ts
|
|
@@ -40294,10 +40359,24 @@ function registerGitHubTools(server) {
|
|
|
40294
40359
|
}
|
|
40295
40360
|
const result = await createPhaseIssue(phase_number, phase_name, goal, requirements, success_criteria);
|
|
40296
40361
|
if (!result.ok) return mcpError(`Phase issue creation failed: ${result.error}`, "Creation failed");
|
|
40297
|
-
|
|
40362
|
+
const responseData = {
|
|
40298
40363
|
issue_number: result.data.number,
|
|
40299
40364
|
issue_id: result.data.id
|
|
40300
|
-
}
|
|
40365
|
+
};
|
|
40366
|
+
const cwd = detectProjectRoot();
|
|
40367
|
+
if (cwd) {
|
|
40368
|
+
const mapping = loadMapping(cwd);
|
|
40369
|
+
if (mapping && mapping.project_number) {
|
|
40370
|
+
const addResult = await addItemToProject(mapping.project_number, result.data.number);
|
|
40371
|
+
if (addResult.ok) {
|
|
40372
|
+
responseData.item_id = addResult.data.itemId;
|
|
40373
|
+
responseData.project_number = mapping.project_number;
|
|
40374
|
+
const moveResult = await moveItemToStatus(mapping.project_number, addResult.data.itemId, "To Do");
|
|
40375
|
+
if (!moveResult.ok) responseData.board_warning = `Added to board but could not set status: ${moveResult.error}`;
|
|
40376
|
+
} else responseData.board_warning = `Issue created but could not add to board: ${addResult.error}`;
|
|
40377
|
+
}
|
|
40378
|
+
}
|
|
40379
|
+
return mcpSuccess(responseData, `Created phase issue #${result.data.number}: [Phase ${phase_number}] ${phase_name}`);
|
|
40301
40380
|
} catch (e) {
|
|
40302
40381
|
return mcpError(e.message, "Operation failed");
|
|
40303
40382
|
}
|
|
@@ -40318,11 +40397,24 @@ function registerGitHubTools(server) {
|
|
|
40318
40397
|
}
|
|
40319
40398
|
const result = await createTaskSubIssue(phase_number, task_id, title, body, parent_issue_number);
|
|
40320
40399
|
if (!result.ok) return mcpError(`Task issue creation failed: ${result.error}`, "Creation failed");
|
|
40321
|
-
|
|
40400
|
+
const responseData = {
|
|
40322
40401
|
issue_number: result.data.number,
|
|
40323
40402
|
issue_id: result.data.id,
|
|
40324
40403
|
parent_issue_number
|
|
40325
|
-
}
|
|
40404
|
+
};
|
|
40405
|
+
const cwd = detectProjectRoot();
|
|
40406
|
+
if (cwd) try {
|
|
40407
|
+
updateTaskMapping(cwd, phase_number, task_id, {
|
|
40408
|
+
number: result.data.number,
|
|
40409
|
+
id: result.data.id,
|
|
40410
|
+
node_id: "",
|
|
40411
|
+
item_id: "",
|
|
40412
|
+
status: "To Do"
|
|
40413
|
+
});
|
|
40414
|
+
} catch (mappingErr) {
|
|
40415
|
+
responseData.mapping_warning = `Issue created but mapping update failed: ${mappingErr.message}`;
|
|
40416
|
+
}
|
|
40417
|
+
return mcpSuccess(responseData, `Created task sub-issue #${result.data.number}: ${title}`);
|
|
40326
40418
|
} catch (e) {
|
|
40327
40419
|
return mcpError(e.message, "Operation failed");
|
|
40328
40420
|
}
|
|
@@ -40350,10 +40442,11 @@ function registerGitHubTools(server) {
|
|
|
40350
40442
|
return mcpError(e.message, "Operation failed");
|
|
40351
40443
|
}
|
|
40352
40444
|
});
|
|
40353
|
-
server.tool("mcp_close_issue", "Close a GitHub issue as completed.", {
|
|
40445
|
+
server.tool("mcp_close_issue", "Close a GitHub issue as completed or not planned.", {
|
|
40354
40446
|
issue_number: numberType().describe("GitHub issue number"),
|
|
40355
|
-
reason: stringType().optional().describe("Optional reason comment to post before closing")
|
|
40356
|
-
|
|
40447
|
+
reason: stringType().optional().describe("Optional reason comment to post before closing"),
|
|
40448
|
+
state_reason: enumType(["completed", "not_planned"]).optional().default("completed").describe("Close reason: completed (default) or not_planned (rollback)")
|
|
40449
|
+
}, async ({ issue_number, reason, state_reason }) => {
|
|
40357
40450
|
try {
|
|
40358
40451
|
try {
|
|
40359
40452
|
requireAuth();
|
|
@@ -40361,12 +40454,13 @@ function registerGitHubTools(server) {
|
|
|
40361
40454
|
if (e instanceof AuthError) return mcpAuthError$1(e);
|
|
40362
40455
|
throw e;
|
|
40363
40456
|
}
|
|
40364
|
-
const result = await closeIssue(issue_number, reason);
|
|
40457
|
+
const result = await closeIssue(issue_number, reason, state_reason);
|
|
40365
40458
|
if (!result.ok) return mcpError(`Close failed: ${result.error}`, "Close failed");
|
|
40366
40459
|
return mcpSuccess({
|
|
40367
40460
|
issue_number,
|
|
40368
|
-
closed: true
|
|
40369
|
-
|
|
40461
|
+
closed: true,
|
|
40462
|
+
state_reason
|
|
40463
|
+
}, `Issue #${issue_number} closed (${state_reason})`);
|
|
40370
40464
|
} catch (e) {
|
|
40371
40465
|
return mcpError(e.message, "Operation failed");
|
|
40372
40466
|
}
|
|
@@ -40405,7 +40499,10 @@ function registerGitHubTools(server) {
|
|
|
40405
40499
|
id: issue.id,
|
|
40406
40500
|
title: issue.title,
|
|
40407
40501
|
state: issue.state,
|
|
40408
|
-
body: issue.body
|
|
40502
|
+
body: issue.body,
|
|
40503
|
+
updated_at: issue.updated_at,
|
|
40504
|
+
labels: issue.labels,
|
|
40505
|
+
comments_url: issue.comments_url
|
|
40409
40506
|
}, `Issue #${issue.number}: ${issue.title} (${issue.state})`);
|
|
40410
40507
|
} catch (e) {
|
|
40411
40508
|
return mcpError(e.message, "Operation failed");
|
|
@@ -40482,6 +40579,136 @@ function registerGitHubTools(server) {
|
|
|
40482
40579
|
return mcpError(e.message, "Operation failed");
|
|
40483
40580
|
}
|
|
40484
40581
|
});
|
|
40582
|
+
server.tool("mcp_post_comment", "Post a comment on a GitHub issue.", {
|
|
40583
|
+
issue_number: numberType().describe("GitHub issue number"),
|
|
40584
|
+
body: stringType().describe("Comment body (markdown)"),
|
|
40585
|
+
type: enumType([
|
|
40586
|
+
"research",
|
|
40587
|
+
"context",
|
|
40588
|
+
"summary",
|
|
40589
|
+
"verification",
|
|
40590
|
+
"uat",
|
|
40591
|
+
"general"
|
|
40592
|
+
]).optional().describe("Comment type for structured header")
|
|
40593
|
+
}, async ({ issue_number, body, type }) => {
|
|
40594
|
+
try {
|
|
40595
|
+
try {
|
|
40596
|
+
requireAuth();
|
|
40597
|
+
} catch (e) {
|
|
40598
|
+
if (e instanceof AuthError) return mcpAuthError$1(e);
|
|
40599
|
+
throw e;
|
|
40600
|
+
}
|
|
40601
|
+
const result = await postComment(issue_number, type ? `<!-- maxsim:type=${type} -->\n${body}` : body);
|
|
40602
|
+
if (!result.ok) return mcpError(`Comment failed: ${result.error}`, "Comment failed");
|
|
40603
|
+
return mcpSuccess({
|
|
40604
|
+
issue_number,
|
|
40605
|
+
comment_id: result.data.commentId,
|
|
40606
|
+
type: type ?? "general"
|
|
40607
|
+
}, `Comment posted on issue #${issue_number}`);
|
|
40608
|
+
} catch (e) {
|
|
40609
|
+
return mcpError(e.message, "Operation failed");
|
|
40610
|
+
}
|
|
40611
|
+
});
|
|
40612
|
+
server.tool("mcp_batch_create_tasks", "Create multiple task sub-issues for a phase with automatic rollback on failure.", {
|
|
40613
|
+
phase_number: stringType().describe("Phase number (e.g. \"01\")"),
|
|
40614
|
+
parent_issue_number: numberType().describe("Parent phase issue number"),
|
|
40615
|
+
tasks: arrayType(objectType({
|
|
40616
|
+
task_id: stringType().describe("Task ID within the phase"),
|
|
40617
|
+
title: stringType().describe("Task title"),
|
|
40618
|
+
body: stringType().describe("Task body (markdown)")
|
|
40619
|
+
})).describe("List of tasks to create")
|
|
40620
|
+
}, async ({ phase_number, parent_issue_number, tasks }) => {
|
|
40621
|
+
try {
|
|
40622
|
+
try {
|
|
40623
|
+
requireAuth();
|
|
40624
|
+
} catch (e) {
|
|
40625
|
+
if (e instanceof AuthError) return mcpAuthError$1(e);
|
|
40626
|
+
throw e;
|
|
40627
|
+
}
|
|
40628
|
+
const succeeded = [];
|
|
40629
|
+
const failed = [];
|
|
40630
|
+
const created = [];
|
|
40631
|
+
for (const task of tasks) {
|
|
40632
|
+
const result = await createTaskSubIssue(phase_number, task.task_id, task.title, task.body, parent_issue_number);
|
|
40633
|
+
if (result.ok) {
|
|
40634
|
+
created.push({
|
|
40635
|
+
issueNumber: result.data.number,
|
|
40636
|
+
taskId: task.task_id
|
|
40637
|
+
});
|
|
40638
|
+
succeeded.push({
|
|
40639
|
+
task_id: task.task_id,
|
|
40640
|
+
issue_number: result.data.number
|
|
40641
|
+
});
|
|
40642
|
+
const cwd = detectProjectRoot();
|
|
40643
|
+
if (cwd) try {
|
|
40644
|
+
updateTaskMapping(cwd, phase_number, task.task_id, {
|
|
40645
|
+
number: result.data.number,
|
|
40646
|
+
id: result.data.id,
|
|
40647
|
+
node_id: "",
|
|
40648
|
+
item_id: "",
|
|
40649
|
+
status: "To Do"
|
|
40650
|
+
});
|
|
40651
|
+
} catch {}
|
|
40652
|
+
} else {
|
|
40653
|
+
failed.push({
|
|
40654
|
+
task_id: task.task_id,
|
|
40655
|
+
error: result.error
|
|
40656
|
+
});
|
|
40657
|
+
const rolledBack = [];
|
|
40658
|
+
for (const c of [...created].reverse()) if ((await closeIssue(c.issueNumber, "[MAXSIM-ROLLBACK] Partial batch failure", "not_planned")).ok) rolledBack.push(c.issueNumber);
|
|
40659
|
+
return mcpSuccess({
|
|
40660
|
+
succeeded,
|
|
40661
|
+
failed,
|
|
40662
|
+
rolled_back: rolledBack,
|
|
40663
|
+
partial: true
|
|
40664
|
+
}, `Batch failed at task "${task.task_id}". Rolled back ${rolledBack.length} issue(s).`);
|
|
40665
|
+
}
|
|
40666
|
+
}
|
|
40667
|
+
return mcpSuccess({
|
|
40668
|
+
succeeded,
|
|
40669
|
+
failed,
|
|
40670
|
+
rolled_back: [],
|
|
40671
|
+
partial: false
|
|
40672
|
+
}, `Batch created ${succeeded.length} task issue(s) for phase ${phase_number}`);
|
|
40673
|
+
} catch (e) {
|
|
40674
|
+
return mcpError(e.message, "Operation failed");
|
|
40675
|
+
}
|
|
40676
|
+
});
|
|
40677
|
+
server.tool("mcp_detect_external_edits", "Check if a phase issue body was modified outside MAXSIM.", { phase_number: stringType().describe("Phase number (e.g. \"01\")") }, async ({ phase_number }) => {
|
|
40678
|
+
try {
|
|
40679
|
+
try {
|
|
40680
|
+
requireAuth();
|
|
40681
|
+
} catch (e) {
|
|
40682
|
+
if (e instanceof AuthError) return mcpAuthError$1(e);
|
|
40683
|
+
throw e;
|
|
40684
|
+
}
|
|
40685
|
+
const cwd = detectProjectRoot();
|
|
40686
|
+
if (!cwd) return mcpError("No .planning/ directory found", "Project not detected");
|
|
40687
|
+
const mapping = loadMapping(cwd);
|
|
40688
|
+
if (!mapping) return mcpError("github-issues.json not found. Run project setup first.", "Mapping missing");
|
|
40689
|
+
const phaseMapping = mapping.phases[phase_number];
|
|
40690
|
+
if (!phaseMapping) return mcpError(`Phase ${phase_number} not found in mapping`, "Phase not found");
|
|
40691
|
+
const storedHash = phaseMapping.body_hash;
|
|
40692
|
+
const issueNumber = phaseMapping.tracking_issue.number;
|
|
40693
|
+
const issueResult = await getPhaseIssue(issueNumber);
|
|
40694
|
+
if (!issueResult.ok) return mcpError(`Failed to fetch issue #${issueNumber}: ${issueResult.error}`, "Fetch failed");
|
|
40695
|
+
const liveHash = hashBody(issueResult.data.body);
|
|
40696
|
+
if (!storedHash) return mcpSuccess({
|
|
40697
|
+
modified: false,
|
|
40698
|
+
phase_number,
|
|
40699
|
+
issue_number: issueNumber,
|
|
40700
|
+
note: "No stored hash — baseline not yet established"
|
|
40701
|
+
}, `Phase ${phase_number}: no baseline hash stored`);
|
|
40702
|
+
const modified = liveHash !== storedHash;
|
|
40703
|
+
return mcpSuccess({
|
|
40704
|
+
modified,
|
|
40705
|
+
phase_number,
|
|
40706
|
+
issue_number: issueNumber
|
|
40707
|
+
}, modified ? `Phase ${phase_number} issue #${issueNumber} has been externally modified` : `Phase ${phase_number} issue #${issueNumber} matches stored hash`);
|
|
40708
|
+
} catch (e) {
|
|
40709
|
+
return mcpError(e.message, "Operation failed");
|
|
40710
|
+
}
|
|
40711
|
+
});
|
|
40485
40712
|
}
|
|
40486
40713
|
|
|
40487
40714
|
//#endregion
|
|
@@ -40567,6 +40794,57 @@ function registerBoardTools(server) {
|
|
|
40567
40794
|
return mcpError(e.message, "Operation failed");
|
|
40568
40795
|
}
|
|
40569
40796
|
});
|
|
40797
|
+
server.tool("mcp_sync_check", "Verify local github-issues.json mapping is in sync with live GitHub state.", {}, async () => {
|
|
40798
|
+
try {
|
|
40799
|
+
try {
|
|
40800
|
+
requireAuth();
|
|
40801
|
+
} catch (e) {
|
|
40802
|
+
if (e instanceof AuthError) return mcpAuthError(e);
|
|
40803
|
+
throw e;
|
|
40804
|
+
}
|
|
40805
|
+
const cwd = detectProjectRoot();
|
|
40806
|
+
if (!cwd) return mcpError("No .planning/ directory found", "Project not detected");
|
|
40807
|
+
const mapping = loadMapping(cwd);
|
|
40808
|
+
if (!mapping) return mcpError("github-issues.json not found. Run project setup first.", "Mapping missing");
|
|
40809
|
+
const mismatches = [];
|
|
40810
|
+
const missing_remote = [];
|
|
40811
|
+
for (const [phaseNum, phaseMapping] of Object.entries(mapping.phases)) {
|
|
40812
|
+
const issueNumber = phaseMapping.tracking_issue.number;
|
|
40813
|
+
if (!issueNumber) continue;
|
|
40814
|
+
const issueResult = await getPhaseIssue(issueNumber);
|
|
40815
|
+
if (!issueResult.ok) {
|
|
40816
|
+
if (issueResult.error.includes("NOT_FOUND") || issueResult.error.includes("404")) missing_remote.push({
|
|
40817
|
+
phase_number: phaseNum,
|
|
40818
|
+
issue_number: issueNumber
|
|
40819
|
+
});
|
|
40820
|
+
continue;
|
|
40821
|
+
}
|
|
40822
|
+
const localStatus = phaseMapping.tracking_issue.status;
|
|
40823
|
+
const remoteState = issueResult.data.state;
|
|
40824
|
+
if (remoteState === "closed" && localStatus !== "Done") mismatches.push({
|
|
40825
|
+
phase_number: phaseNum,
|
|
40826
|
+
issue_number: issueNumber,
|
|
40827
|
+
local_state: localStatus,
|
|
40828
|
+
remote_state: remoteState
|
|
40829
|
+
});
|
|
40830
|
+
else if (remoteState === "open" && localStatus === "Done") mismatches.push({
|
|
40831
|
+
phase_number: phaseNum,
|
|
40832
|
+
issue_number: issueNumber,
|
|
40833
|
+
local_state: localStatus,
|
|
40834
|
+
remote_state: remoteState
|
|
40835
|
+
});
|
|
40836
|
+
}
|
|
40837
|
+
const in_sync = mismatches.length === 0 && missing_remote.length === 0;
|
|
40838
|
+
return mcpSuccess({
|
|
40839
|
+
in_sync,
|
|
40840
|
+
mismatches,
|
|
40841
|
+
missing_local: [],
|
|
40842
|
+
missing_remote
|
|
40843
|
+
}, in_sync ? "Local mapping is in sync with GitHub" : `Sync issues found: ${mismatches.length} mismatch(es), ${missing_remote.length} missing remote`);
|
|
40844
|
+
} catch (e) {
|
|
40845
|
+
return mcpError(e.message, "Operation failed");
|
|
40846
|
+
}
|
|
40847
|
+
});
|
|
40570
40848
|
server.tool("mcp_search_issues", "Search GitHub issues by label, state, or text query.", {
|
|
40571
40849
|
labels: arrayType(stringType()).optional().describe("Filter by label names"),
|
|
40572
40850
|
state: enumType([
|