Coordinates Serena MCP knowledge graph operations for Shannon Framework. Enforces standardized entity naming (shannon/* namespace), relation creation patterns, search protocols, and observation management. Prevents orphaned entities, naming chaos, and broken context lineage. Use when: storing specs/waves/goals/checkpoints, querying Shannon history, managing knowledge graph structure, ensuring cross-wave context preservation.
Coordinates Serena MCP knowledge graph operations for Shannon Framework. Enforces standardized entity naming (shannon/* namespace), relation creation patterns, search protocols, and observation management. Use when: storing specs/waves/goals/checkpoints, querying Shannon history, managing knowledge graph structure, ensuring cross-wave context preservation.
/plugin marketplace add krzemienski/shannon-framework/plugin install shannon@shannon-frameworkThis skill is limited to using the following tools:
BASELINE_TEST.mdCOMPLETION_REPORT.mdREFACTOR_TESTS.mdexamples/01-querying-wave-history.mdPurpose: Memory Coordination is Shannon's protocol for structured Serena MCP operations. It enforces standardized entity naming (shannon/* namespace), mandatory relation creation, consistent search patterns, and proper observation management to maintain a clean, queryable knowledge graph across all waves and sessions.
When to Use:
Expected Outcomes:
Duration: 10-30 seconds per operation
CRITICAL: Agents systematically rationalize skipping memory-coordination protocols. Below are the 6 most common rationalizations detected in baseline testing, with mandatory counters.
Example: Agent creates entity named "spec_data" or "MyAnalysis" without shannon/ prefix
COUNTER:
Rule: All Shannon entities have shannon/* namespace. No exceptions.
Example: Agent creates wave entity without relating it to spec
COUNTER:
Rule: Create relations. Every entity connects to graph.
Example: Agent searches with random queries: "wave", "Wave 1", "waves", "show waves"
COUNTER:
Rule: Use protocol search patterns. Not creative queries.
Example: Agent creates "spec_002" to update "spec_001" instead of adding observations
COUNTER:
Rule: Updates use add_observations, not create_entities.
Example: Agent creates "goal" entity in root namespace (not shannon/goals/)
COUNTER:
Rule: shannon/* namespace mandatory. Prevents collisions.
Example: Agent calls read_graph() then manually filters for waves
COUNTER:
Rule: Use search_nodes with namespace. Never read_graph for queries.
If you're tempted to:
Then you are rationalizing. Stop. Apply the protocol. Follow the rules.
Use this skill when:
DO NOT use when:
Required:
operation_type (string): Serena operation to perform
"create", "read", "update", "search", "relate", "delete"entity_data (object): Data for the operation
{
"type": "spec" | "wave" | "goal" | "checkpoint" | "sitrep" | "task",
"data": {
"complexity_score": 0.68,
"domain_percentages": {...},
"execution_strategy": "wave-based"
},
"timestamp": "20250104_143022"
}
Optional (operation-specific):
entity_name (string): For read/update/delete operations
"shannon/specs/spec_20250104_143022"search_pattern (string): For search operations
"shannon/waves/" (all waves)"shannon/checkpoints/cp_20250104" (date-filtered)parent_entity (string): For create operations (establishes relation)
"shannon/specs/spec_001" (wave's parent)relation_type (string): For relate operations
"spawns", "contains", "tracks", "created_checkpoint", "implements", "reports_on", "relates_to"observations (array): For create/update operations
["type: spec_analysis", "created: 2025-01-04T14:30:22Z", "complexity_score: 0.68"]Input: Data to store (spec, wave, goal, checkpoint, SITREP)
Processing:
Identify entity type from data structure or user intent
Map to Shannon namespace:
Generate timestamp (MANDATORY FORMAT):
const timestamp = new Date().toISOString()
.replace(/[-:]/g, '')
.replace('T', '_')
.split('.')[0];
// Result: 20250104_143022
Sanitize entity name:
Output: Full entity name (e.g., shannon/specs/spec_20250104_143022)
Duration: 1 second
Input: Entity name, entity type, data
Processing:
[
"type: [entity_type]",
"created: [ISO timestamp]",
"purpose: [description]",
"[key]: [value]",
"[serialized JSON if complex data]"
]
create_entities({
entities: [{
name: "shannon/specs/spec_20250104_143022",
entityType: "Specification",
observations: [
"type: spec_analysis",
"created: 2025-01-04T14:30:22Z",
"complexity_score: 0.68",
"domain: Frontend 38%, Backend 35%, Database 27%",
"execution_strategy: wave-based",
"JSON: {...full analysis...}"
]
}]
})
Output: Entity created, entity name
Duration: 2-3 seconds
Input: New entity name, related entities
Processing:
Identify parent or related entities:
Determine relation type (active voice) with VALIDATION: APPROVED RELATION TYPES:
VALIDATION (prevent typos):
const approved = ["spawns", "contains", "created_checkpoint",
"implements", "reports_on", "tracks", "relates_to"];
if (!approved.includes(relationType)) {
throw Error(`Invalid relationType: ${relationType}. Use one of: ${approved.join(', ')}`);
}
Call create_relations: For SINGLE entity:
create_relations({
relations: [{
from: "shannon/specs/spec_001",
to: "shannon/waves/wave_001",
relationType: "spawns"
}]
})
For BULK operations (50+ entities):
// Create ALL relations in ONE call (not 50 separate calls)
create_relations({
relations: [
{from: "shannon/waves/wave_001", to: "shannon/tasks/task_001", relationType: "contains"},
{from: "shannon/waves/wave_001", to: "shannon/tasks/task_002", relationType: "contains"},
// ... 48 more relations
]
})
Verify relation created
Output: Relations established, connected graph
Duration: 1-2 seconds
Input: Query intent (e.g., "find all waves", "get spec_001", "list checkpoints")
Processing:
Map intent to search pattern:
Execute search with NAMESPACE PRECISION:
// CORRECT: Full namespace
search_nodes("shannon/waves/")
open_nodes(["shannon/specs/spec_20250104_143022"])
// CORRECT: Recent checkpoints (2025-01-04)
search_nodes("shannon/checkpoints/cp_20250104")
// WRONG: Partial match (might hit user entities)
search_nodes("spec_") // ❌ Could match user project entity "spec_data"
search_nodes("wave") // ❌ Ambiguous, no namespace
// WRONG: Root namespace query
search_nodes("spec_001") // ❌ Missing shannon/specs/ prefix
RULE: Always use FULL shannon/* path. Never partial match.
Parse results
Output: Matching entities with observations
Duration: 1-2 seconds
Input: Entity name, new information
Processing:
MANDATORY VERIFICATION (prevent errors):
// ALWAYS verify entity exists BEFORE add_observations
const entity = open_nodes(["shannon/waves/wave_001"]);
if (!entity || entity.length === 0) {
throw Error("Cannot update: entity shannon/waves/wave_001 not found");
}
If entity missing:
Structure new observations:
[
"updated: [ISO timestamp]",
"status: [new status]",
"[new_key]: [new_value]"
]
Call add_observations:
add_observations({
observations: [{
entityName: "shannon/waves/wave_001",
contents: [
"updated: 2025-01-04T15:00:00Z",
"status: Phase 2 complete",
"progress: 60%",
"next_action: Begin Phase 3 implementation"
]
}]
})
OBSERVATION LIMITS (prevent overflow):
Verify update successful
Output: Entity updated with new observations
Duration: 2-3 seconds
Input: Recent operations
Processing:
Check entity naming:
Check relations:
Check operations:
Output: Validation pass/fail, corrections if needed
Duration: 5 seconds
Serena MCP (MANDATORY)
// Create entity
create_entities({
entities: [{
name: "shannon/specs/spec_001",
entityType: "Specification",
observations: ["type: spec_analysis", "created: 2025-01-04T14:30:22Z"]
}]
})
// Create relation
create_relations({
relations: [{
from: "shannon/specs/spec_001",
to: "shannon/waves/wave_001",
relationType: "spawns"
}]
})
// Search
const specs = search_nodes("shannon/specs/")
const wave = open_nodes(["shannon/waves/wave_001"])
// Update
add_observations({
observations: [{
entityName: "shannon/waves/wave_001",
contents: ["status: Phase 2 complete", "progress: 60%"]
}]
})
Input: Spec analysis complete (complexity 0.68, Frontend 38%, Backend 35%, Database 27%)
Execution:
Step 1: Determine entity type
-> Type: Specification
-> Namespace: shannon/specs/
-> Entity name: shannon/specs/spec_20250104_143022
Step 2: Create entity
-> create_entities({
entities: [{
name: "shannon/specs/spec_20250104_143022",
entityType: "Specification",
observations: [
"type: spec_analysis",
"created: 2025-01-04T14:30:22Z",
"complexity_score: 0.68",
"interpretation: Complex",
"domains: Frontend 38%, Backend 35%, Database 27%",
"execution_strategy: wave-based",
"recommended_waves: 3-7",
"recommended_agents: 8-15",
"timeline: 2-4 days",
"JSON: {\"complexity_score\":0.68,\"dimensions\":{...},\"domain_percentages\":{...}}"
]
}]
})
Step 3: Create relations
-> No parent (spec is root entity)
-> Relations will be created when waves spawn from this spec
Step 4: Verify creation
-> open_nodes(["shannon/specs/spec_20250104_143022"])
-> ✅ Entity exists with all observations
Output: Spec stored as shannon/specs/spec_20250104_143022, ready to spawn waves
Input: Starting Wave 1 for spec_20250104_143022
Execution:
Step 1: Determine entity type
-> Type: Wave
-> Namespace: shannon/waves/
-> Entity name: shannon/waves/wave_20250104_150000
Step 2: Create entity
-> create_entities({
entities: [{
name: "shannon/waves/wave_20250104_150000",
entityType: "Wave",
observations: [
"type: wave",
"wave_number: 1",
"created: 2025-01-04T15:00:00Z",
"spec_id: shannon/specs/spec_20250104_143022",
"phase: Phase 2 - Architecture & Design",
"status: in_progress",
"agents: 8",
"start_time: 2025-01-04T15:00:00Z"
]
}]
})
Step 3: Create relations
-> Parent: shannon/specs/spec_20250104_143022
-> Relation: spec "spawns" wave
-> create_relations({
relations: [{
from: "shannon/specs/spec_20250104_143022",
to: "shannon/waves/wave_20250104_150000",
relationType: "spawns"
}]
})
Step 4: Verify
-> open_nodes(["shannon/waves/wave_20250104_150000"])
-> search_nodes("shannon/waves/") shows wave_20250104_150000
-> ✅ Wave created and linked to spec
Output: Wave 1 created, linked to spec via "spawns" relation
Input: User asks "Show me all waves for current project"
Execution:
Step 1: Map query to search pattern
-> Intent: All waves
-> Pattern: search_nodes("shannon/waves/")
Step 2: Execute search
-> search_nodes("shannon/waves/")
-> Returns:
- shannon/waves/wave_20250104_150000
- shannon/waves/wave_20250104_170000
- shannon/waves/wave_20250105_090000
Step 3: Fetch details (if needed)
-> open_nodes([
"shannon/waves/wave_20250104_150000",
"shannon/waves/wave_20250104_170000",
"shannon/waves/wave_20250105_090000"
])
Step 4: Parse observations
-> Wave 1: Phase 2, status: complete
-> Wave 2: Phase 3, status: complete
-> Wave 3: Phase 4, status: in_progress
Step 5: Format output
-> "Wave History:
- Wave 1 (2025-01-04 15:00): Phase 2 complete
- Wave 2 (2025-01-04 17:00): Phase 3 complete
- Wave 3 (2025-01-05 09:00): Phase 4 in progress"
Output: Complete wave history with status, fetched efficiently using namespace search
Input: Wave 1 completed Phase 2, moving to Phase 3
Execution:
Step 1: Identify entity
-> Entity: shannon/waves/wave_20250104_150000
Step 2: Structure update observations
-> [
"updated: 2025-01-04T16:30:00Z",
"status: complete",
"phase_completed: Phase 2 - Architecture & Design",
"next_phase: Phase 3 - Implementation",
"deliverables: Architecture diagrams, API specs, DB schemas",
"validation_gate: ✅ Design approved, patterns established"
]
Step 3: Add observations (NOT create new entity)
-> add_observations({
observations: [{
entityName: "shannon/waves/wave_20250104_150000",
contents: [
"updated: 2025-01-04T16:30:00Z",
"status: complete",
"phase_completed: Phase 2 - Architecture & Design",
"next_phase: Phase 3 - Implementation",
"deliverables: Architecture diagrams, API specs, DB schemas",
"validation_gate: ✅ Design approved, patterns established"
]
}]
})
Step 4: Verify update
-> open_nodes(["shannon/waves/wave_20250104_150000"])
-> ✅ Entity has new observations appended
-> ✅ NO duplicate entity created
Output: Wave 1 updated with completion status, no data duplication
Input: Create checkpoint at end of Wave 1
Execution:
Step 1: Determine entity type
-> Type: Checkpoint
-> Namespace: shannon/checkpoints/
-> Entity name: shannon/checkpoints/cp_20250104_163000
Step 2: Create entity
-> create_entities({
entities: [{
name: "shannon/checkpoints/cp_20250104_163000",
entityType: "Checkpoint",
observations: [
"type: checkpoint",
"created: 2025-01-04T16:30:00Z",
"wave_id: shannon/waves/wave_20250104_150000",
"phase: Phase 2 complete",
"status: Validated",
"files: [list of checkpoint files]",
"context: Architecture design complete, moving to implementation"
]
}]
})
Step 3: Create relations
-> Parent: shannon/waves/wave_20250104_150000
-> Relation: wave "created_checkpoint" checkpoint
-> create_relations({
relations: [{
from: "shannon/waves/wave_20250104_150000",
to: "shannon/checkpoints/cp_20250104_163000",
relationType: "created_checkpoint"
}]
})
Step 4: Verify
-> open_nodes(["shannon/checkpoints/cp_20250104_163000"])
-> ✅ Checkpoint created
-> ✅ Relation exists: wave -> checkpoint
-> ✅ Can trace checkpoint -> wave -> spec lineage
Output: Checkpoint created and linked to wave, context lineage preserved
Operation result object:
{
"operation": "create" | "read" | "update" | "search" | "relate" | "delete",
"success": true,
"entity_name": "shannon/specs/spec_20250104_143022",
"entity_type": "Specification",
"observations": [
"type: spec_analysis",
"created: 2025-01-04T14:30:22Z",
"complexity_score: 0.68",
"domains: Frontend 40%, Backend 35%, Database 25%"
],
"relations": [
{
"from": "shannon/specs/spec_20250104_143022",
"to": "shannon/waves/wave_20250104_150000",
"type": "spawns"
}
],
"validation": {
"namespace_correct": true,
"relations_exist": true,
"format_valid": true,
"no_duplicates": true
},
"lineage": {
"parent": "shannon/specs/spec_20250104_143022",
"children": ["shannon/waves/wave_20250104_150000"],
"depth": 2
}
}
Successful when:
Fails if:
Validation Code:
def validate_memory_coordination(result):
"""Verify memory coordination followed protocols"""
# Check: shannon/* namespace
entity_name = result.get("entity_name", "")
assert entity_name.startswith("shannon/"), \
f"VIOLATION: Entity missing shannon/ prefix: {entity_name}"
# Check: Standard namespace (specs, waves, goals, checkpoints, sitreps, tasks)
valid_namespaces = ["shannon/specs/", "shannon/waves/", "shannon/goals/",
"shannon/checkpoints/", "shannon/sitreps/", "shannon/tasks/"]
assert any(entity_name.startswith(ns) for ns in valid_namespaces), \
f"VIOLATION: Invalid namespace: {entity_name}"
# Check: Relations exist (unless root spec)
if result.get("operation") == "create" and "specs" not in entity_name:
relations = result.get("relations", [])
assert len(relations) >= 1, \
"VIOLATION: Entity created without relations (orphaned)"
# Check: Relations use approved types
approved_relations = ["spawns", "contains", "created_checkpoint",
"implements", "reports_on", "tracks", "relates_to"]
for relation in result.get("relations", []):
assert relation["type"] in approved_relations, \
f"VIOLATION: Invalid relation type: {relation['type']}"
# Check: Observations have timestamps
observations = result.get("observations", [])
has_timestamp = any("created:" in obs or "updated:" in obs for obs in observations)
assert has_timestamp, \
"VIOLATION: Observations missing timestamp"
# Check: No duplicate entities (same data in multiple entities)
validation = result.get("validation", {})
assert validation.get("no_duplicates") == True, \
"VIOLATION: Duplicate entities detected"
# Check: Lineage traceable
lineage = result.get("lineage", {})
if "specs" not in entity_name: # Non-root entities
assert lineage.get("parent") is not None, \
"VIOLATION: Cannot trace lineage (broken relations)"
return True
Problem: Agent creates "spec_001" instead of "shannon/specs/spec_001"
Why It Fails:
Solution: ALWAYS prefix with shannon/[type]s/ (specs, waves, goals, checkpoints, sitreps)
Prevention: Validation rejects entities without shannon/ prefix
Problem: Agent creates wave entity but forgets to link to parent spec
Why It Fails:
Solution: EVERY entity MUST have >=1 relation (except root specs)
Prevention: Step 3 mandatory relation creation, validation checks
Problem: Agent creates "spec_002" to update "spec_001" instead of adding observations
Why It Fails:
Solution: Use add_observations for updates, NOT create_entities
Prevention: Skill emphasizes update protocol, anti-rationalization section
Problem: Agent calls read_graph() then manually filters for waves
Why It Fails:
Solution: Use search_nodes("shannon/waves/") for targeted query
Prevention: Step 4 search patterns, avoid read_graph() for queries
Problem: Agent creates shannon/specs/spec_001, shannon/specs/specification_002, shannon/specs/my_spec_3
Why It Fails:
Solution: Standardize: shannon/specs/spec_[timestamp] or shannon/specs/spec_[id]
Prevention: Step 1 entity naming protocol, examples show standard format
Problem: Agent creates observations without timestamps (["status: complete", "progress: 100%"])
Why It Fails:
Solution: ALWAYS include timestamp in observations: ["updated: 2025-01-04T16:30:00Z", "status: complete"]
Prevention: Step 2 and Step 5 observation format includes timestamps
How to verify memory-coordination executed correctly:
Check Entity Names:
Check Relations:
Check Operations:
Check Observations:
Test Queries:
Test Lineage:
SKILL.md (This file): ~600 lines
references/: No deep references needed (protocol is self-contained)
Claude loads references/ when: N/A (all protocol details in SKILL.md)
Version: 4.0.0 Last Updated: 2025-11-04 Author: Shannon Framework Team License: MIT Status: Core (Protocol skill, mandatory for Serena MCP operations)
This skill should be used when the user asks to "create a slash command", "add a command", "write a custom command", "define command arguments", "use command frontmatter", "organize commands", "create command with file references", "interactive command", "use AskUserQuestion in command", or needs guidance on slash command structure, YAML frontmatter fields, dynamic arguments, bash execution in commands, user interaction patterns, or command development best practices for Claude Code.
This skill should be used when the user asks to "create an agent", "add an agent", "write a subagent", "agent frontmatter", "when to use description", "agent examples", "agent tools", "agent colors", "autonomous agent", or needs guidance on agent structure, system prompts, triggering conditions, or agent development best practices for Claude Code plugins.
This skill should be used when the user asks to "create a hook", "add a PreToolUse/PostToolUse/Stop hook", "validate tool use", "implement prompt-based hooks", "use ${CLAUDE_PLUGIN_ROOT}", "set up event-driven automation", "block dangerous commands", or mentions hook events (PreToolUse, PostToolUse, Stop, SubagentStop, SessionStart, SessionEnd, UserPromptSubmit, PreCompact, Notification). Provides comprehensive guidance for creating and implementing Claude Code plugin hooks with focus on advanced prompt-based hooks API.