internaltool-mcp 1.6.17 → 1.6.19

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 +59 -14
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -346,25 +346,16 @@ Set confirmed=false first to preview, then confirmed=true to execute everything.
346
346
  } catch { /* remote branch may not exist */ }
347
347
  }
348
348
 
349
- if (uncommitted) {
350
- return text({
351
- blocked: true,
352
- reason: 'You have uncommitted local changes.',
353
- fix: 'Commit your changes first, then call park_task again.',
354
- commands: ['git add .', 'git commit -m "wip: parking task — <describe what you did>"'],
355
- message: 'Cannot park until all changes are committed.',
356
- })
357
- }
358
-
359
349
  if (!confirmed) {
360
350
  return text({
361
351
  preview: {
362
352
  task: task ? { key: task.key, title: task.title, branch: task.github?.headBranch || null } : null,
363
353
  parkNote: { summary: summary || '(empty)', remaining: remaining || '(empty)', blockers: blockers || '(empty)' },
364
354
  willAutomate: [
365
- unpushedCount > 0 ? `Push ${unpushedCount} unpushed commit(s) to remote` : 'Branch is already up to date on remote',
355
+ uncommitted ? `Auto-commit uncommitted changes with message: "wip(${task?.key?.toLowerCase()}): ${(summary || 'parking task').slice(0, 60)}"` : null,
356
+ unpushedCount > 0 || uncommitted ? `Push branch to remote` : 'Branch is already up to date on remote',
366
357
  'Save park note to task',
367
- task?.cursorRules?.trim() ? 'Delete cursor rules file (.cursor/rules/' + task.key?.toLowerCase() + '.mdc)' : null,
358
+ task?.cursorRules?.trim() ? `Delete cursor rules file (.cursor/rules/${task.key?.toLowerCase()}.mdc)` : null,
368
359
  'Post handoff comment on the task',
369
360
  'Notify project members',
370
361
  ].filter(Boolean),
@@ -374,6 +365,18 @@ Set confirmed=false first to preview, then confirmed=true to execute everything.
374
365
  })
375
366
  }
376
367
 
368
+ // ── Auto-commit if there are uncommitted changes ───────────────────────
369
+ if (repoRoot && uncommitted) {
370
+ try {
371
+ const commitMsg = `wip(${task?.key?.toLowerCase() || 'task'}): ${(summary || 'parking task').slice(0, 60)}`
372
+ runGit('add -A', repoRoot)
373
+ runGit(`commit -m "${commitMsg}"`, repoRoot)
374
+ unpushedCount += 1 // just committed, so now there's something to push
375
+ } catch (e) {
376
+ return text({ blocked: true, reason: `Auto-commit failed: ${e.message.split('\n')[0]}. Commit manually then call park_task again.` })
377
+ }
378
+ }
379
+
377
380
  // ── Auto-push unpushed commits ─────────────────────────────────────────
378
381
  let pushed = false
379
382
  if (repoRoot && currentBranch && unpushedCount > 0) {
@@ -482,9 +485,25 @@ Set confirmed=false first to read everything, then confirmed=true to execute.`,
482
485
  runGit('fetch origin', repoRoot)
483
486
  runGit(`checkout ${branch}`, repoRoot)
484
487
  runGit(`pull origin ${branch}`, repoRoot)
485
- gitResult = { switched: true, branch }
488
+
489
+ // Auto-rebase from main so Dev B starts on a clean, up-to-date branch
490
+ let rebaseResult = null
491
+ try {
492
+ const behind = parseInt(runGit(`rev-list HEAD..origin/main --count`, repoRoot).trim(), 10) || 0
493
+ if (behind > 0) {
494
+ runGit('rebase origin/main', repoRoot)
495
+ runGit(`push origin ${branch} --force-with-lease`, repoRoot)
496
+ rebaseResult = { rebased: true, commitsBehind: behind, message: `Auto-rebased ${behind} commit(s) from main — branch is now up to date` }
497
+ } else {
498
+ rebaseResult = { rebased: false, message: 'Branch is already up to date with main' }
499
+ }
500
+ } catch (rebaseErr) {
501
+ rebaseResult = { rebased: false, conflict: true, message: 'Auto-rebase failed — merge conflict detected. Run: git rebase origin/main and resolve conflicts manually.' }
502
+ }
503
+
504
+ gitResult = { switched: true, branch, rebase: rebaseResult }
486
505
  } catch (e) {
487
- gitResult = { switched: false, error: e.message.split('\n')[0], manualSteps: [`git fetch origin`, `git checkout ${branch}`, `git pull origin ${branch}`] }
506
+ gitResult = { switched: false, error: e.message.split('\n')[0], manualSteps: [`git fetch origin`, `git checkout ${branch}`, `git pull origin ${branch}`, 'git rebase origin/main'] }
488
507
  }
489
508
  }
490
509
 
@@ -2453,6 +2472,32 @@ branchAction values (only needed when current branch ≠ task branch):
2453
2472
  ...unsafeUntracked.map(f => `⚠️ SKIP: ${f} ← do not commit this`),
2454
2473
  ]
2455
2474
 
2475
+ // ── Block if task is parked — prevent Dev A pushing after handoff ────────
2476
+ if (task) {
2477
+ const isParked = !!(task.parkNote?.parkedAt)
2478
+ const currentOwner = task.parkNote?.currentOwner
2479
+ const parkedBy = task.parkNote?.parkedBy
2480
+ let meId = ''
2481
+ try { const me = await api.get('/api/auth/me'); meId = me?.data?.user?._id || me?.data?._id || '' } catch { /* non-fatal */ }
2482
+
2483
+ if (isParked && parkedBy && parkedBy.toString() === meId) {
2484
+ return text({
2485
+ blocked: true,
2486
+ reason: `You parked "${task.title}". Another developer may have picked it up.`,
2487
+ advice: 'Check the task on the board before pushing. If you still own it, call unpark_task first, then commit.',
2488
+ message: 'Commit blocked — task is parked.',
2489
+ })
2490
+ }
2491
+ if (currentOwner && currentOwner.toString() !== meId && meId) {
2492
+ return text({
2493
+ blocked: true,
2494
+ reason: `"${task.title}" is currently owned by another developer who unparked it.`,
2495
+ advice: 'Do not push to this branch. Coordinate with the current owner first.',
2496
+ message: 'Commit blocked — another developer owns this task.',
2497
+ })
2498
+ }
2499
+ }
2500
+
2456
2501
  // ── PREVIEW (confirmed=false) ─────────────────────────────────────────────
2457
2502
  if (!confirmed) {
2458
2503
  // Case 1: branch mismatch — must resolve before anything else
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "internaltool-mcp",
3
- "version": "1.6.17",
3
+ "version": "1.6.19",
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",