internaltool-mcp 1.6.3 → 1.6.5

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.
Files changed (2) hide show
  1. package/index.js +80 -8
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -851,7 +851,8 @@ Use this when a developer says "start task", "brief me on", or "what do I need t
851
851
  .replace(/[^a-z0-9]+/g, '-')
852
852
  .slice(0, 40)}`
853
853
 
854
- const hasReadme = typeof task.readmeMarkdown === 'string' && task.readmeMarkdown.trim().length > 0
854
+ const hasReadme = typeof task.readmeMarkdown === 'string' && task.readmeMarkdown.trim().length > 0
855
+ const hasCursorRules = typeof task.cursorRules === 'string' && task.cursorRules.trim().length > 0
855
856
  const subtasks = (task.subtasks || []).map(s => ({
856
857
  title: s.title,
857
858
  done: s.done,
@@ -861,6 +862,39 @@ Use this when a developer says "start task", "brief me on", or "what do I need t
861
862
  const subtasksTotal = subtasks.length
862
863
 
863
864
  // ── Preview: show the full plan before touching anything ──
865
+ const approvalState = task.approval?.state || 'none'
866
+ const approvalBlocks = ['backlog', 'todo'].includes(task.column) && approvalState !== 'approved'
867
+
868
+ // Build the next-step roadmap so developer knows exactly what comes after reading the plan
869
+ let workflowRoadmap
870
+ if (!hasReadme) {
871
+ workflowRoadmap = [
872
+ `1. Write the implementation plan — click "Start writing" on the Plan tab`,
873
+ `2. Call submit_task_for_approval to send it for review`,
874
+ `3. After approval, call create_branch — the task moves to In progress automatically`,
875
+ ]
876
+ } else if (approvalState === 'none') {
877
+ workflowRoadmap = [
878
+ `1. ✅ Implementation plan is written — read it above`,
879
+ `2. Call submit_task_for_approval with taskId="${taskId}" to send it for review`,
880
+ `3. After approval, call create_branch — the task moves to In progress automatically`,
881
+ ]
882
+ } else if (approvalState === 'pending') {
883
+ workflowRoadmap = [
884
+ `1. ✅ Implementation plan written`,
885
+ `2. ⏳ Waiting for reviewer approval`,
886
+ `3. After approval, call create_branch — the task moves to In progress automatically`,
887
+ ]
888
+ } else {
889
+ // approved
890
+ workflowRoadmap = [
891
+ `1. ✅ Implementation plan written and approved`,
892
+ `2. Call create_branch with taskId="${taskId}" — moves task to In progress automatically`,
893
+ `3. Code → commit (use commit_helper) → push`,
894
+ `4. Call raise_pr — task moves to In review automatically`,
895
+ ]
896
+ }
897
+
864
898
  if (!confirmed) {
865
899
  return text({
866
900
  brief: {
@@ -868,24 +902,31 @@ Use this when a developer says "start task", "brief me on", or "what do I need t
868
902
  title: task.title,
869
903
  priority: task.priority,
870
904
  description: task.description || '(no description)',
871
- // The implementation plan — Claude must read and present this to the developer
872
905
  implementationPlan: hasReadme
873
906
  ? task.readmeMarkdown
874
- : '⚠️ No implementation plan (README) found for this task. The developer should write one before starting work.',
907
+ : '⚠️ No implementation plan found. Write one in the Plan tab before starting work.',
875
908
  subtasks: subtasksTotal > 0
876
909
  ? { items: subtasks, progress: `${subtasksDone}/${subtasksTotal} done` }
877
910
  : null,
878
- approvalState: task.approval?.state || 'none',
911
+ approvalState,
879
912
  },
880
913
  meta: {
881
914
  currentColumn: task.column,
882
- willMoveTo: 'in_progress',
883
915
  suggestedBranch,
884
916
  },
917
+ workflowRoadmap,
918
+ approvalWarning: approvalBlocks
919
+ ? approvalState === 'pending'
920
+ ? `⏳ Plan is submitted and awaiting approval — you cannot create a branch until it is approved.`
921
+ : `⚠️ Plan is not yet submitted for approval. Submit it first, then create the branch.`
922
+ : null,
923
+ cursorRules: hasCursorRules
924
+ ? { active: true, rules: task.cursorRules, instruction: '⚠️ CURSOR RULES ACTIVE — You MUST follow every rule in the "rules" field above for the entire duration of this task. These rules override your defaults.' }
925
+ : { active: false, rules: null, instruction: 'No task-specific Cursor rules set for this task.' },
885
926
  requiresConfirmation: true,
886
- message: hasReadme
887
- ? `Read the implementation plan above carefully, then call kickoff_task again with confirmed=true to start the task.`
888
- : `⚠️ This task has no implementation plan. Consider writing one first (use update_task with readmeMarkdown), then confirm to start anyway.`,
927
+ message: approvalBlocks
928
+ ? `Read the plan above, then follow workflowRoadmap approval is required before you can branch and start coding.`
929
+ : `Read the implementation plan above carefully, then call kickoff_task again with confirmed=true.`,
889
930
  })
890
931
  }
891
932
 
@@ -917,6 +958,9 @@ Use this when a developer says "start task", "brief me on", or "what do I need t
917
958
  subtasks,
918
959
  },
919
960
  implementationPlan: hasReadme ? task.readmeMarkdown : null,
961
+ cursorRules: hasCursorRules
962
+ ? { active: true, rules: task.cursorRules, instruction: '⚠️ CURSOR RULES ACTIVE — You MUST follow every rule in the "rules" field for the entire duration of this task.' }
963
+ : { active: false },
920
964
  recentCommits: recentCommits.slice(0, 5).map(c => ({
921
965
  sha: c.sha?.slice(0, 7),
922
966
  message: c.commit?.message?.split('\n')[0],
@@ -1443,6 +1487,34 @@ If you have uncommitted tracked changes, it will tell you exactly what to do bef
1443
1487
  if (!taskRes?.success) return errorText('Task not found')
1444
1488
  const task = taskRes.data.task
1445
1489
 
1490
+ // ── Approval gate check ───────────────────────────────────────────────────
1491
+ // The server blocks non-admins from moving todo → in_progress without approval.
1492
+ // Detect this early and guide the developer instead of failing silently after branch creation.
1493
+ const approvalState = task.approval?.state || 'none'
1494
+ const PLANNING_COLS = ['backlog', 'todo']
1495
+ const needsApproval = PLANNING_COLS.includes(task.column) && approvalState !== 'approved'
1496
+ if (needsApproval && !confirmed) {
1497
+ const isFix2 = /\b(fix|bug|hotfix|patch)\b/i.test(task.title + ' ' + (task.description || ''))
1498
+ const slug2 = task.title.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '').slice(0, 35)
1499
+ const previewBranch = `${isFix2 ? 'fix' : 'feature'}/${task.key.toLowerCase()}-${slug2}`
1500
+ return text({
1501
+ blocked: true,
1502
+ reason: 'approval_required',
1503
+ task: { key: task.key, title: task.title, column: task.column, approvalState },
1504
+ message: `The task's implementation plan (README) must be approved before creating a branch and moving to In progress.`,
1505
+ approvalStatus: approvalState === 'pending'
1506
+ ? `Plan is already submitted and waiting for reviewer approval. Once approved, call create_branch again.`
1507
+ : `Plan has not been submitted for review yet.`,
1508
+ nextSteps: approvalState === 'pending'
1509
+ ? [`Wait for the reviewer to approve, then call create_branch with taskId="${taskId}"`]
1510
+ : [
1511
+ `1. Make sure the README / implementation plan is written on the task (use update_task with readmeMarkdown if needed)`,
1512
+ `2. Call submit_task_for_approval with taskId="${taskId}" and the reviewerId of your project lead`,
1513
+ `3. Once approved, call create_branch again — it will create "${previewBranch}" and move the task to In progress automatically`,
1514
+ ],
1515
+ })
1516
+ }
1517
+
1446
1518
  const isFix = /\b(fix|bug|hotfix|patch)\b/i.test(task.title + ' ' + (task.description || ''))
1447
1519
  const prefix = isFix ? 'fix' : 'feature'
1448
1520
  const slug = task.title
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "internaltool-mcp",
3
- "version": "1.6.3",
3
+ "version": "1.6.5",
4
4
  "description": "MCP server for InternalTool — connect AI assistants (Claude Code, Cursor) to your project and task management platform",
5
5
  "type": "module",
6
6
  "main": "index.js",