claude-multi-session 2.6.0 → 2.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/bin/setup.js CHANGED
@@ -125,6 +125,8 @@ The tool automatically:
125
125
  Returns a structured pass/fail report with recommendation.
126
126
  PROCEED ONLY IF the report says ALL CHECKS PASSED.
127
127
 
128
+ **ENFORCED:** \`team_spawn\` will return an error if \`phase_gate\` was not called between spawn batches. The first batch (Phase 0) is free; every subsequent batch requires a passing \`phase_gate\` call first.
129
+
128
130
  Count your phases upfront. If you have N phases, fill in this checkpoint exactly N-1 times (between every adjacent pair of phases). Skipping verification for later phases is the #1 cause of test failures.
129
131
 
130
132
  Only intervene in workers when a session is BLOCKED or FAILED.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-multi-session",
3
- "version": "2.6.0",
3
+ "version": "2.7.0",
4
4
  "description": "Multi-session orchestrator for Claude Code CLI — spawn, control, pause, resume, and send multiple inputs to Claude Code sessions programmatically",
5
5
  "main": "src/index.js",
6
6
  "bin": {
package/src/mcp-server.js CHANGED
@@ -76,6 +76,10 @@ let pipelineEngine = null;
76
76
  let snapshotEngine = null;
77
77
  let currentTeamName = null;
78
78
 
79
+ // Phase gate enforcement state — tracks gate calls vs spawn batches per team
80
+ // team -> { gateCount: number, spawnBatchCount: number, lastSpawnTime: number }
81
+ const _gateState = new Map();
82
+
79
83
  /**
80
84
  * Get or create Team Hub instances for a given team
81
85
  * This function lazily creates the instances on first use
@@ -1748,6 +1752,31 @@ async function handleTeamSpawn(args) {
1748
1752
  const teamName = args.team || 'default';
1749
1753
  const { teamHub } = getTeamInstances(teamName);
1750
1754
 
1755
+ // Gate enforcement: require phase_gate between spawn batches
1756
+ const state = _gateState.get(teamName) || { gateCount: 0, spawnBatchCount: 0, lastSpawnTime: 0 };
1757
+ const now = Date.now();
1758
+
1759
+ // Detect new spawn batch (>5s since last spawn = new batch)
1760
+ const isNewBatch = (now - state.lastSpawnTime) > 5000;
1761
+ if (isNewBatch) {
1762
+ state.spawnBatchCount++;
1763
+ }
1764
+ state.lastSpawnTime = now;
1765
+ _gateState.set(teamName, state);
1766
+
1767
+ // Rule: spawnBatchCount must be <= gateCount + 1
1768
+ // (first batch is free, every subsequent batch needs a gate)
1769
+ if (state.spawnBatchCount > state.gateCount + 1) {
1770
+ return errorResult(
1771
+ `PHASE GATE REQUIRED: You have spawned ${state.spawnBatchCount - 1} batch(es) of workers ` +
1772
+ `but only called phase_gate ${state.gateCount} time(s). ` +
1773
+ `Call phase_gate() to verify the previous phase completed before spawning more workers.\n\n` +
1774
+ `Example:\n` +
1775
+ `phase_gate({ phase_completing: "Phase N", phase_starting: "Phase N+1", ` +
1776
+ `expected_artifacts: ["..."] })`
1777
+ );
1778
+ }
1779
+
1751
1780
  // Join the team roster
1752
1781
  teamHub.joinTeam(args.name, {
1753
1782
  role: args.role || 'team member',
@@ -2769,6 +2798,14 @@ function handlePhaseGate(args) {
2769
2798
  // Overall pass/fail
2770
2799
  report.passed = report.checks.every(c => c.passed);
2771
2800
 
2801
+ // Track gate pass for spawn enforcement
2802
+ if (report.passed) {
2803
+ const state = _gateState.get(teamName) || { gateCount: 0, spawnBatchCount: 0, lastSpawnTime: 0 };
2804
+ state.gateCount++;
2805
+ _gateState.set(teamName, state);
2806
+ report._gate_generation = state.gateCount;
2807
+ }
2808
+
2772
2809
  // Action recommendation
2773
2810
  if (report.passed) {
2774
2811
  report.recommendation = `ALL CHECKS PASSED. Safe to proceed to ${args.phase_starting}.`;
@@ -2895,6 +2932,9 @@ function handleTeamReset(args) {
2895
2932
  snapshotEngine = null;
2896
2933
  currentTeamName = null;
2897
2934
 
2935
+ // Clear gate enforcement state
2936
+ _gateState.delete(teamName);
2937
+
2898
2938
  summary.message = `Team "${teamName}" has been reset. ${summary.cleared.length} stores cleared.`;
2899
2939
 
2900
2940
  return textResult(JSON.stringify(summary, null, 2));
package/src/prompts.js CHANGED
@@ -608,6 +608,8 @@ The tool automatically:
608
608
  Returns a structured pass/fail report with recommendation.
609
609
  PROCEED ONLY IF the report says ALL CHECKS PASSED.
610
610
 
611
+ **ENFORCED:** \`team_spawn\` will return an error if \`phase_gate\` was not called between spawn batches. The first batch (Phase 0) is free; every subsequent batch requires a passing \`phase_gate\` call first.
612
+
611
613
  === PHASE COUNTING RULE ===
612
614
  At the start of planning, count and list your phases explicitly:
613
615
  "Phase 0: [foundation], Phase 1: [routes], Phase 2: [tests], ..."
@@ -919,6 +921,8 @@ IMPORTANT: You are the ORCHESTRATOR. Your job is to PLAN, SPAWN, and MONITOR —
919
921
 
920
922
  5. **Post-Phase Verification** — After each phase completes, call \`phase_gate()\` which runs ALL verification checks in one call: confirms artifacts exist, validates content, checks workers are idle, and verifies artifact readers. Only proceed when it reports ALL CHECKS PASSED. If you have N phases, verify N-1 times.
921
923
 
924
+ **Note:** \`team_spawn\` will return an error if \`phase_gate\` was not called between spawn batches. The first batch (Phase 0) is free; every subsequent batch requires a passing \`phase_gate\` call first.
925
+
922
926
  6. **Collect** — When all workers are idle, check \`artifact_list\` for published outputs and summarize results for the user.
923
927
 
924
928
  ### Critical Rule: Never Assign the Same File to Two Workers