claude-multi-session 2.3.1 → 2.4.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/package.json +1 -1
- package/src/artifact-store.js +50 -0
- package/src/mcp-server.js +129 -4
- package/src/prompts.js +81 -25
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-multi-session",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.4.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/artifact-store.js
CHANGED
|
@@ -469,6 +469,45 @@ class ArtifactStore {
|
|
|
469
469
|
}
|
|
470
470
|
}
|
|
471
471
|
|
|
472
|
+
/**
|
|
473
|
+
* Track that a session read an artifact
|
|
474
|
+
* @param {string} artifactId - The artifact that was read
|
|
475
|
+
* @param {string} reader - The session name that read it
|
|
476
|
+
* @param {number} version - The version that was read
|
|
477
|
+
*/
|
|
478
|
+
trackRead(artifactId, reader, version) {
|
|
479
|
+
if (!reader) return; // Skip if no reader identified
|
|
480
|
+
|
|
481
|
+
const readsPath = path.join(this.dataDir, artifactId, 'reads.json');
|
|
482
|
+
|
|
483
|
+
// Read existing reads log
|
|
484
|
+
let reads = readJsonSafe(readsPath, []);
|
|
485
|
+
|
|
486
|
+
// Add this read event
|
|
487
|
+
reads.push({
|
|
488
|
+
reader,
|
|
489
|
+
version,
|
|
490
|
+
readAt: new Date().toISOString(),
|
|
491
|
+
});
|
|
492
|
+
|
|
493
|
+
// Write back (not immutable — reads are append-only log)
|
|
494
|
+
const dir = path.join(this.dataDir, artifactId);
|
|
495
|
+
if (!fs.existsSync(dir)) {
|
|
496
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
497
|
+
}
|
|
498
|
+
fs.writeFileSync(readsPath, JSON.stringify(reads, null, 2));
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
/**
|
|
502
|
+
* Get the read log for an artifact
|
|
503
|
+
* @param {string} artifactId - The artifact to check
|
|
504
|
+
* @returns {Array} Array of read events: [{ reader, version, readAt }]
|
|
505
|
+
*/
|
|
506
|
+
getReads(artifactId) {
|
|
507
|
+
const readsPath = path.join(this.dataDir, artifactId, 'reads.json');
|
|
508
|
+
return readJsonSafe(readsPath, []);
|
|
509
|
+
}
|
|
510
|
+
|
|
472
511
|
/**
|
|
473
512
|
* List artifacts with optional filtering
|
|
474
513
|
* @param {Object} [filters={}] - Filter criteria
|
|
@@ -497,6 +536,17 @@ class ArtifactStore {
|
|
|
497
536
|
results = results.filter(item => item.tags && item.tags.includes(tag));
|
|
498
537
|
}
|
|
499
538
|
|
|
539
|
+
// Enrich with read counts
|
|
540
|
+
results = results.map(item => {
|
|
541
|
+
const reads = this.getReads(item.artifactId);
|
|
542
|
+
const uniqueReaders = [...new Set(reads.map(r => r.reader))];
|
|
543
|
+
return {
|
|
544
|
+
...item,
|
|
545
|
+
readCount: reads.length,
|
|
546
|
+
uniqueReaders,
|
|
547
|
+
};
|
|
548
|
+
});
|
|
549
|
+
|
|
500
550
|
return results;
|
|
501
551
|
}
|
|
502
552
|
|
package/src/mcp-server.js
CHANGED
|
@@ -25,6 +25,8 @@
|
|
|
25
25
|
* - tools/call → execute a tool and return result
|
|
26
26
|
*/
|
|
27
27
|
|
|
28
|
+
const fs = require('fs');
|
|
29
|
+
const path = require('path');
|
|
28
30
|
const readline = require('readline');
|
|
29
31
|
const SessionManager = require('./manager');
|
|
30
32
|
const Delegate = require('./delegate');
|
|
@@ -47,6 +49,9 @@ const DecisionJournal = require('./decision-journal');
|
|
|
47
49
|
const PatternRegistry = require('./pattern-registry');
|
|
48
50
|
const StaleDetector = require('./stale-detector');
|
|
49
51
|
|
|
52
|
+
// Capture version at load time — used to detect stale server processes
|
|
53
|
+
const LOADED_VERSION = require('../package.json').version;
|
|
54
|
+
|
|
50
55
|
// =============================================================================
|
|
51
56
|
// Server State — persists across all tool calls
|
|
52
57
|
// =============================================================================
|
|
@@ -390,6 +395,18 @@ const TOOLS = [
|
|
|
390
395
|
},
|
|
391
396
|
},
|
|
392
397
|
|
|
398
|
+
// ── Server Version ─────────────────────────────────────────────────────
|
|
399
|
+
{
|
|
400
|
+
name: 'server_version',
|
|
401
|
+
description:
|
|
402
|
+
'Check the running MCP server version and detect staleness. ' +
|
|
403
|
+
'Call this if tools seem missing or behave unexpectedly.',
|
|
404
|
+
inputSchema: {
|
|
405
|
+
type: 'object',
|
|
406
|
+
properties: {},
|
|
407
|
+
},
|
|
408
|
+
},
|
|
409
|
+
|
|
393
410
|
// ══════════════════════════════════════════════════════════════════════════
|
|
394
411
|
// TEAM HUB v2 — 32 new tools for team collaboration
|
|
395
412
|
// ══════════════════════════════════════════════════════════════════════════
|
|
@@ -555,12 +572,15 @@ const TOOLS = [
|
|
|
555
572
|
{
|
|
556
573
|
name: 'artifact_get',
|
|
557
574
|
description:
|
|
558
|
-
'Read an artifact (latest version or specific version).'
|
|
575
|
+
'Read an artifact (latest version or specific version). ' +
|
|
576
|
+
'IMPORTANT: Pass your session name as the "reader" parameter to track artifact consumption. ' +
|
|
577
|
+
'The orchestrator uses this to verify workers actually read shared data.',
|
|
559
578
|
inputSchema: {
|
|
560
579
|
type: 'object',
|
|
561
580
|
properties: {
|
|
562
581
|
artifactId: { type: 'string', description: 'Artifact ID to retrieve' },
|
|
563
582
|
version: { type: 'number', description: 'Specific version number (omit for latest)' },
|
|
583
|
+
reader: { type: 'string', description: 'Session name reading this artifact (for tracking who consumed it)' },
|
|
564
584
|
team: { type: 'string', description: 'Team name (default: "default")' },
|
|
565
585
|
},
|
|
566
586
|
required: ['artifactId'],
|
|
@@ -582,6 +602,20 @@ const TOOLS = [
|
|
|
582
602
|
},
|
|
583
603
|
},
|
|
584
604
|
|
|
605
|
+
{
|
|
606
|
+
name: 'artifact_readers',
|
|
607
|
+
description:
|
|
608
|
+
'Check who has read a specific artifact. Use this to verify that workers actually consumed shared artifacts like conventions or schemas.',
|
|
609
|
+
inputSchema: {
|
|
610
|
+
type: 'object',
|
|
611
|
+
properties: {
|
|
612
|
+
artifactId: { type: 'string', description: 'Artifact ID to check readers for' },
|
|
613
|
+
team: { type: 'string', description: 'Team name (default: "default")' },
|
|
614
|
+
},
|
|
615
|
+
required: ['artifactId'],
|
|
616
|
+
},
|
|
617
|
+
},
|
|
618
|
+
|
|
585
619
|
{
|
|
586
620
|
name: 'artifact_history',
|
|
587
621
|
description:
|
|
@@ -1124,6 +1158,10 @@ async function executeTool(toolName, args) {
|
|
|
1124
1158
|
case 'abort_task':
|
|
1125
1159
|
return handleAbort(args);
|
|
1126
1160
|
|
|
1161
|
+
// ── Server Version ──────────────────────────────────────────────
|
|
1162
|
+
case 'server_version':
|
|
1163
|
+
return handleServerVersion(args);
|
|
1164
|
+
|
|
1127
1165
|
// ── Orchestrator Guide ────────────────────────────────────────────
|
|
1128
1166
|
case 'get_orchestrator_guide':
|
|
1129
1167
|
return handleGetOrchestratorGuide(args);
|
|
@@ -1161,6 +1199,8 @@ async function executeTool(toolName, args) {
|
|
|
1161
1199
|
return handleArtifactGet(args);
|
|
1162
1200
|
case 'artifact_list':
|
|
1163
1201
|
return handleArtifactList(args);
|
|
1202
|
+
case 'artifact_readers':
|
|
1203
|
+
return handleArtifactReaders(args);
|
|
1164
1204
|
case 'artifact_history':
|
|
1165
1205
|
return handleArtifactHistory(args);
|
|
1166
1206
|
|
|
@@ -1580,6 +1620,32 @@ function handleGetOrchestratorGuide(args) {
|
|
|
1580
1620
|
return textResult(guide);
|
|
1581
1621
|
}
|
|
1582
1622
|
|
|
1623
|
+
/**
|
|
1624
|
+
* Check the running MCP server version and detect staleness.
|
|
1625
|
+
* Compares the version loaded into memory at startup against the
|
|
1626
|
+
* version currently installed on disk (package.json).
|
|
1627
|
+
*/
|
|
1628
|
+
function handleServerVersion() {
|
|
1629
|
+
let installedVersion = LOADED_VERSION;
|
|
1630
|
+
try {
|
|
1631
|
+
const pkgPath = path.join(__dirname, '..', 'package.json');
|
|
1632
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
|
|
1633
|
+
installedVersion = pkg.version;
|
|
1634
|
+
} catch (e) {
|
|
1635
|
+
// If we can't read package.json at runtime, use loaded version
|
|
1636
|
+
}
|
|
1637
|
+
|
|
1638
|
+
const stale = LOADED_VERSION !== installedVersion;
|
|
1639
|
+
return textResult(JSON.stringify({
|
|
1640
|
+
running: LOADED_VERSION,
|
|
1641
|
+
installed: installedVersion,
|
|
1642
|
+
stale,
|
|
1643
|
+
message: stale
|
|
1644
|
+
? `Server is stale: running v${LOADED_VERSION} but v${installedVersion} is installed. Restart Claude Code to load new tools.`
|
|
1645
|
+
: `Server is up to date (v${LOADED_VERSION}).`
|
|
1646
|
+
}, null, 2));
|
|
1647
|
+
}
|
|
1648
|
+
|
|
1583
1649
|
// =============================================================================
|
|
1584
1650
|
// Team Hub Handlers — Layer 1, 2, 3
|
|
1585
1651
|
// =============================================================================
|
|
@@ -1867,7 +1933,13 @@ function handleArtifactGet(args) {
|
|
|
1867
1933
|
return errorResult(`Artifact ${args.artifactId} not found`);
|
|
1868
1934
|
}
|
|
1869
1935
|
|
|
1870
|
-
|
|
1936
|
+
// Track this read if a reader was specified
|
|
1937
|
+
if (args.reader) {
|
|
1938
|
+
artifactStore.trackRead(args.artifactId, args.reader, artifact.version);
|
|
1939
|
+
}
|
|
1940
|
+
|
|
1941
|
+
// Build the response
|
|
1942
|
+
const response = {
|
|
1871
1943
|
artifactId: artifact.artifactId,
|
|
1872
1944
|
version: artifact.version,
|
|
1873
1945
|
type: artifact.type,
|
|
@@ -1878,7 +1950,15 @@ function handleArtifactGet(args) {
|
|
|
1878
1950
|
summary: artifact.summary,
|
|
1879
1951
|
lineage: artifact.lineage,
|
|
1880
1952
|
team: teamName,
|
|
1881
|
-
|
|
1953
|
+
readBy: artifactStore.getReads(args.artifactId),
|
|
1954
|
+
};
|
|
1955
|
+
|
|
1956
|
+
// Add nudge if reader param was not provided
|
|
1957
|
+
if (!args.reader) {
|
|
1958
|
+
response._hint = 'Tip: Pass your session name as the "reader" parameter to track artifact consumption. Example: artifact_get({ artifactId: "...", reader: "your-session-name" })';
|
|
1959
|
+
}
|
|
1960
|
+
|
|
1961
|
+
return textResult(JSON.stringify(response, null, 2));
|
|
1882
1962
|
} catch (err) {
|
|
1883
1963
|
return errorResult(err.message);
|
|
1884
1964
|
}
|
|
@@ -1908,6 +1988,8 @@ function handleArtifactList(args) {
|
|
|
1908
1988
|
createdAt: a.createdAt,
|
|
1909
1989
|
updatedAt: a.updatedAt,
|
|
1910
1990
|
tags: a.tags,
|
|
1991
|
+
readCount: a.readCount,
|
|
1992
|
+
uniqueReaders: a.uniqueReaders,
|
|
1911
1993
|
})),
|
|
1912
1994
|
}, null, 2));
|
|
1913
1995
|
} catch (err) {
|
|
@@ -1915,6 +1997,25 @@ function handleArtifactList(args) {
|
|
|
1915
1997
|
}
|
|
1916
1998
|
}
|
|
1917
1999
|
|
|
2000
|
+
function handleArtifactReaders(args) {
|
|
2001
|
+
try {
|
|
2002
|
+
const teamName = args.team || 'default';
|
|
2003
|
+
const { artifactStore } = getTeamInstances(teamName);
|
|
2004
|
+
|
|
2005
|
+
const reads = artifactStore.getReads(args.artifactId);
|
|
2006
|
+
const uniqueReaders = [...new Set(reads.map(r => r.reader))];
|
|
2007
|
+
|
|
2008
|
+
return textResult(JSON.stringify({
|
|
2009
|
+
artifactId: args.artifactId,
|
|
2010
|
+
totalReads: reads.length,
|
|
2011
|
+
uniqueReaders,
|
|
2012
|
+
reads,
|
|
2013
|
+
}, null, 2));
|
|
2014
|
+
} catch (err) {
|
|
2015
|
+
return errorResult(err.message);
|
|
2016
|
+
}
|
|
2017
|
+
}
|
|
2018
|
+
|
|
1918
2019
|
function handleArtifactHistory(args) {
|
|
1919
2020
|
try {
|
|
1920
2021
|
const teamName = args.team || 'default';
|
|
@@ -2453,6 +2554,28 @@ function errorResult(message) {
|
|
|
2453
2554
|
return { content: [{ type: 'text', text: `Error: ${message}` }], isError: true };
|
|
2454
2555
|
}
|
|
2455
2556
|
|
|
2557
|
+
/**
|
|
2558
|
+
* Append a staleness warning to tool results if the server version is outdated.
|
|
2559
|
+
* Reads package.json from disk on each call to detect post-install version drift.
|
|
2560
|
+
* @param {Object} result - The tool result object
|
|
2561
|
+
* @returns {Object} The result, possibly with a staleness warning appended
|
|
2562
|
+
*/
|
|
2563
|
+
function appendStalenessWarning(result) {
|
|
2564
|
+
try {
|
|
2565
|
+
const pkgPath = path.join(__dirname, '..', 'package.json');
|
|
2566
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
|
|
2567
|
+
if (pkg.version !== LOADED_VERSION) {
|
|
2568
|
+
const warning = `\n\n⚠️ STALE SERVER: Running v${LOADED_VERSION} but v${pkg.version} is installed. Restart Claude Code to load updated tools.`;
|
|
2569
|
+
if (result && result.content && result.content[0] && result.content[0].text) {
|
|
2570
|
+
result.content[0].text += warning;
|
|
2571
|
+
}
|
|
2572
|
+
}
|
|
2573
|
+
} catch (e) {
|
|
2574
|
+
// Silently ignore — staleness check is best-effort
|
|
2575
|
+
}
|
|
2576
|
+
return result;
|
|
2577
|
+
}
|
|
2578
|
+
|
|
2456
2579
|
// =============================================================================
|
|
2457
2580
|
// MCP Protocol Handler — JSON-RPC 2.0 over stdio
|
|
2458
2581
|
// =============================================================================
|
|
@@ -2522,7 +2645,9 @@ async function handleMessage(message) {
|
|
|
2522
2645
|
break;
|
|
2523
2646
|
}
|
|
2524
2647
|
try {
|
|
2525
|
-
|
|
2648
|
+
let result = await executeTool(params.name, params.arguments || {});
|
|
2649
|
+
// Append staleness warning if server version is outdated
|
|
2650
|
+
result = appendStalenessWarning(result);
|
|
2526
2651
|
sendResponse(id, result);
|
|
2527
2652
|
} catch (err) {
|
|
2528
2653
|
sendResponse(id, errorResult(err.message));
|
package/src/prompts.js
CHANGED
|
@@ -66,15 +66,25 @@ Your inbox may contain:
|
|
|
66
66
|
- Dependency artifacts you need before starting
|
|
67
67
|
- Updated instructions from the orchestrator
|
|
68
68
|
|
|
69
|
-
### Step 1.5: CHECK FOR SHARED CONVENTIONS
|
|
70
|
-
Call \`mcp__multi-session__artifact_list\` and look for
|
|
71
|
-
|
|
72
|
-
|
|
69
|
+
### Step 1.5: CHECK FOR SHARED CONVENTIONS AND DEPENDENCY ARTIFACTS
|
|
70
|
+
Call \`mcp__multi-session__artifact_list\` and look for:
|
|
71
|
+
- A conventions or API contract artifact (e.g., "shared-conventions")
|
|
72
|
+
- Any dependency artifacts your task requires (e.g., "db-schema" if you're building routes)
|
|
73
73
|
|
|
74
|
-
If
|
|
74
|
+
If found, call \`mcp__multi-session__artifact_get\` with your session name as the \`reader\` parameter:
|
|
75
|
+
\`\`\`
|
|
76
|
+
mcp__multi-session__artifact_get({ artifactId: "shared-conventions", reader: "${name}" })
|
|
77
|
+
mcp__multi-session__artifact_get({ artifactId: "db-schema", reader: "${name}" })
|
|
78
|
+
\`\`\`
|
|
79
|
+
|
|
80
|
+
IMPORTANT: The \`reader\` parameter tracks that you consumed the artifact. This is how the orchestrator verifies workers actually read shared data. ALWAYS include your session name as \`reader\`.
|
|
81
|
+
|
|
82
|
+
Follow the conventions STRICTLY. If NO convention artifact exists AND your work must match other workers' output:
|
|
75
83
|
- Use \`team_ask\` to ask the relevant teammate about their format BEFORE writing code
|
|
76
84
|
- NEVER guess or assume format — mismatches cause test failures
|
|
77
85
|
|
|
86
|
+
Note: team_ask is a **fallback mechanism** for when information wasn't available upfront. If your orchestrator provided thorough prompts with all needed context and conventions, you may never need team_ask — this is the ideal case.
|
|
87
|
+
|
|
78
88
|
### Step 2: UPDATE YOUR STATUS
|
|
79
89
|
Call \`mcp__multi-session__team_update_status\` to set yourself as "active" with your current task.
|
|
80
90
|
|
|
@@ -112,7 +122,7 @@ mcp__multi-session__team_broadcast({ from: "${name}", content: "Completed: <what
|
|
|
112
122
|
| \`team_check_inbox\` | BEFORE starting work, AFTER major steps |
|
|
113
123
|
| \`team_send_message\` | Direct message to a specific teammate |
|
|
114
124
|
| \`team_broadcast\` | Announce something to ALL teammates |
|
|
115
|
-
| \`team_ask\` | Ask a teammate a question and WAIT for reply |
|
|
125
|
+
| \`team_ask\` | Ask a teammate a question and WAIT for reply (fallback — use when info wasn't provided upfront) |
|
|
116
126
|
| \`team_reply\` | Reply to a question you received (IMMEDIATELY) |
|
|
117
127
|
| \`team_update_status\` | Update what you're working on |
|
|
118
128
|
|
|
@@ -466,8 +476,9 @@ IMPORTANT: You are the ORCHESTRATOR. Your job is to PLAN, SPAWN, and MONITOR —
|
|
|
466
476
|
|
|
467
477
|
=== CRITICAL: ANTI-PATTERN — DO NOT DO THIS ===
|
|
468
478
|
- Do NOT spawn a session, read its output, then manually relay that output to another session
|
|
469
|
-
- Do NOT fix bugs found by one session yourself
|
|
479
|
+
- Do NOT fix bugs found by one session yourself UNLESS the fix is ≤ 3 lines AND the worker session has completed. For trivial fixes, you may fix directly but MUST broadcast the change and re-publish any affected artifacts
|
|
470
480
|
- Do NOT act as a message router between sessions — they can talk directly
|
|
481
|
+
- Note: team_ask is a **fallback** for unexpected ambiguity. In well-orchestrated projects where you provide all context upfront in worker prompts, team_ask may never be called — this is the ideal case and means your prompts were thorough enough.
|
|
471
482
|
- Do NOT do implementation work that should be delegated
|
|
472
483
|
- Do NOT fix code yourself when a worker's tests fail — send corrections to the worker that wrote the failing code
|
|
473
484
|
- Do NOT assume workers will agree on response formats — define shared conventions before spawning
|
|
@@ -517,6 +528,34 @@ mcp__multi-session__artifact_publish({
|
|
|
517
528
|
|
|
518
529
|
NEVER assume workers will independently agree on conventions. Define them explicitly.
|
|
519
530
|
|
|
531
|
+
### Phase Gate: VERIFY Before Spawning
|
|
532
|
+
=== CRITICAL: MANDATORY VERIFICATION STEP ===
|
|
533
|
+
Before spawning ANY worker that depends on a previous phase's output, you MUST:
|
|
534
|
+
1. Call \`artifact_list()\` to confirm the dependency artifact was published
|
|
535
|
+
2. Call \`artifact_get(artifactId)\` to confirm the artifact contains valid data
|
|
536
|
+
3. ONLY THEN spawn the dependent workers
|
|
537
|
+
|
|
538
|
+
Example phased workflow:
|
|
539
|
+
\`\`\`
|
|
540
|
+
// Phase 1: Spawn the database worker
|
|
541
|
+
team_spawn({ name: "db-worker", ... })
|
|
542
|
+
|
|
543
|
+
// PHASE GATE: Verify before Phase 2
|
|
544
|
+
artifact_list() // Confirm "db-schema" appears
|
|
545
|
+
artifact_get({ artifactId: "db-schema" }) // Confirm it has valid table definitions
|
|
546
|
+
|
|
547
|
+
// Phase 2: NOW spawn route workers (they depend on the schema)
|
|
548
|
+
team_spawn({ name: "api-worker", ... })
|
|
549
|
+
team_spawn({ name: "test-worker", ... })
|
|
550
|
+
\`\`\`
|
|
551
|
+
|
|
552
|
+
NEVER skip verification. NEVER rely on a worker's self-reported completion — verify the artifact exists yourself.
|
|
553
|
+
|
|
554
|
+
=== PHASE COUNTING RULE ===
|
|
555
|
+
At the start of planning, count and list your phases explicitly:
|
|
556
|
+
"Phase 1: [description], Phase 2: [description], ..."
|
|
557
|
+
This creates a self-check — you can verify you ran the verification checklist between each pair.
|
|
558
|
+
|
|
520
559
|
### Phase 2: Spawn Workers (use team_spawn, NOT delegate_task)
|
|
521
560
|
Spawn all independent workers at once. Example:
|
|
522
561
|
|
|
@@ -565,18 +604,16 @@ mcp__multi-session__contract_create({
|
|
|
565
604
|
})
|
|
566
605
|
\`\`\`
|
|
567
606
|
|
|
568
|
-
### Phase 4:
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
\`\`\`
|
|
607
|
+
### Phase 4: Post-Phase Verification (MANDATORY)
|
|
608
|
+
After ALL workers in a phase complete, and BEFORE spawning the next phase, you MUST run this verification checklist:
|
|
609
|
+
|
|
610
|
+
1. \`artifact_list()\` — confirm all expected artifacts from this phase exist
|
|
611
|
+
2. \`artifact_get()\` on each critical artifact — verify the content is valid and complete
|
|
612
|
+
3. \`team_roster()\` — confirm all phase workers show 'idle' or 'done' status
|
|
575
613
|
|
|
576
|
-
Only
|
|
577
|
-
|
|
578
|
-
-
|
|
579
|
-
- The user asks for a status update
|
|
614
|
+
Only proceed to the next phase when ALL checks pass.
|
|
615
|
+
|
|
616
|
+
IMPORTANT: Count your phases at the start of planning. If you have N phases, you MUST perform this verification checklist exactly N-1 times (between every adjacent pair of phases). Skipping verification for later phases is the #1 cause of test failures in multi-session projects.
|
|
580
617
|
|
|
581
618
|
### Phase 5: Collect Results
|
|
582
619
|
When all workers are done:
|
|
@@ -726,6 +763,7 @@ const ROLE_PROMPTS = {
|
|
|
726
763
|
- Publish test results as artifacts with type "test-results" including: passed, failed, skipped counts and failure details
|
|
727
764
|
- If tests fail due to bugs in another session's code, use \`team_send_message\` to notify them with the exact error and file path
|
|
728
765
|
- Use the correct status values as defined in the database schema (e.g., "in_progress" not "in-progress")
|
|
766
|
+
- IMPORTANT: When calling artifact_get, ALWAYS include reader: "<your-session-name>" so the orchestrator can verify you read the artifacts
|
|
729
767
|
`,
|
|
730
768
|
|
|
731
769
|
'database': `
|
|
@@ -822,7 +860,9 @@ IMPORTANT: You are the ORCHESTRATOR. Your job is to PLAN, SPAWN, and MONITOR —
|
|
|
822
860
|
|
|
823
861
|
4. **Set up dependencies** — Use \`contract_create\` if Task B needs output from Task A.
|
|
824
862
|
|
|
825
|
-
5. **
|
|
863
|
+
4.5. **Phase Gate** — Before spawning workers that depend on previous workers' output, VERIFY the dependency artifact exists by calling \`artifact_list()\` and \`artifact_get()\`. Never trust self-reported completion — verify the artifact.
|
|
864
|
+
|
|
865
|
+
5. **Post-Phase Verification** — After each phase completes, run the verification checklist: \`artifact_list()\` to confirm artifacts exist, \`artifact_get()\` to verify content, \`team_roster()\` to confirm workers are idle. Only proceed when all checks pass. If you have N phases, verify N-1 times.
|
|
826
866
|
|
|
827
867
|
6. **Collect** — When all workers are idle, check \`artifact_list\` for published outputs and summarize results for the user.
|
|
828
868
|
|
|
@@ -907,14 +947,30 @@ WHY: Specific file, exact error, expected behavior, and how to verify.
|
|
|
907
947
|
`;
|
|
908
948
|
|
|
909
949
|
const ORCHESTRATOR_MONITORING = `
|
|
910
|
-
##
|
|
950
|
+
## Post-Phase Verification (MANDATORY)
|
|
951
|
+
|
|
952
|
+
After ALL workers in a phase complete, and BEFORE spawning the next phase, you MUST run this verification checklist. Do NOT fall back to filesystem checks (Glob, Read) to verify worker output — use these tools:
|
|
911
953
|
|
|
912
|
-
|
|
954
|
+
### Verification Checklist (run between EVERY pair of phases)
|
|
955
|
+
\`\`\`
|
|
956
|
+
mcp__multi-session__artifact_list() — Confirm all expected artifacts from this phase exist
|
|
957
|
+
mcp__multi-session__artifact_get() — Verify each critical artifact has valid, complete content
|
|
958
|
+
mcp__multi-session__team_roster() — Confirm all phase workers show 'idle' or 'done' status
|
|
959
|
+
\`\`\`
|
|
960
|
+
|
|
961
|
+
Only proceed to the next phase when ALL checks pass.
|
|
962
|
+
|
|
963
|
+
### Dependency Verification
|
|
964
|
+
Between spawn phases, use these to verify dependencies:
|
|
965
|
+
\`\`\`
|
|
966
|
+
mcp__multi-session__artifact_get({ artifactId: "db-schema" }) — Verify artifact content
|
|
967
|
+
mcp__multi-session__artifact_readers({ artifactId: "db-schema" }) — Check who read it
|
|
968
|
+
\`\`\`
|
|
913
969
|
|
|
970
|
+
After all workers complete, verify every worker consumed the artifacts they needed:
|
|
914
971
|
\`\`\`
|
|
915
|
-
mcp__multi-
|
|
916
|
-
|
|
917
|
-
mcp__multi-session__artifact_list() — See published outputs
|
|
972
|
+
mcp__multi-session__artifact_readers({ artifactId: "shared-conventions" })
|
|
973
|
+
// Should list ALL route workers as readers
|
|
918
974
|
\`\`\`
|
|
919
975
|
|
|
920
976
|
### When to Intervene
|
|
@@ -937,7 +993,7 @@ When a worker is BLOCKED:
|
|
|
937
993
|
|
|
938
994
|
NEVER do these:
|
|
939
995
|
- Do NOT read the worker's full output to understand the problem — their status message should tell you
|
|
940
|
-
- Do NOT implement
|
|
996
|
+
- Do NOT implement fixes > 3 lines yourself — tell the worker to fix it or spawn a fix-worker. For trivial fixes (≤ 3 lines) where the worker is already done, you may fix directly but MUST broadcast the change and re-publish affected artifacts
|
|
941
997
|
- Do NOT act as a message router between workers — they can use \`team_ask\` directly
|
|
942
998
|
|
|
943
999
|
=== ANTI-PATTERN — DO NOT DO THIS ===
|