| name | memory-coordination |
| description | 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. |
| skill-type | PROTOCOL |
| shannon-version | >=4.0.0 |
| mcp-requirements | [object Object] |
| required-sub-skills | |
| optional-sub-skills | |
| allowed-tools | Serena |
Memory Coordination
Overview
Purpose: 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:
- Storing ANY Shannon artifact (spec, wave, goal, checkpoint, SITREP)
- Querying Shannon history (waves, checkpoints, specs)
- Creating entities for Shannon context preservation
- Updating existing entities with new information
- Establishing relations between Shannon entities
- Searching Shannon knowledge graph
Expected Outcomes:
- Standardized entity names with shannon/* namespace
- Complete relational graph (no orphaned entities)
- Efficient queries using consistent patterns
- Cross-wave context preservation
- Zero data duplication via observations
- Clean knowledge graph structure
Duration: 10-30 seconds per operation
Anti-Rationalization (From Baseline Testing)
CRITICAL: Agents systematically rationalize skipping memory-coordination protocols. Below are the 6 most common rationalizations detected in baseline testing, with mandatory counters.
Rationalization 1: "Entity name seems fine"
Example: Agent creates entity named "spec_data" or "MyAnalysis" without shannon/ prefix
COUNTER:
- ❌ NEVER create Shannon entities without shannon/* namespace
- ✅ ALL Shannon entities MUST start with shannon/
- ✅ Use standard namespaces: shannon/specs/, shannon/waves/, shannon/goals/, shannon/checkpoints/, shannon/sitreps/
- ✅ If name lacks shannon/ prefix, it's WRONG
Rule: All Shannon entities have shannon/* namespace. No exceptions.
Rationalization 2: "Relations not needed for this entity"
Example: Agent creates wave entity without relating it to spec
COUNTER:
- ❌ NEVER create standalone Shannon entities
- ✅ EVERY entity has at least 1 relation (usually to parent or creator)
- ✅ Spec -> spawns -> Wave, Wave -> contains -> Task, Wave -> created_checkpoint -> Checkpoint
- ✅ Orphaned entities = broken context lineage
Rule: Create relations. Every entity connects to graph.
Rationalization 3: "Search query seems reasonable"
Example: Agent searches with random queries: "wave", "Wave 1", "waves", "show waves"
COUNTER:
- ❌ NEVER use free-form search queries for Shannon entities
- ✅ Use EXACT search patterns defined in this skill
- ✅ Search specs: search_nodes("shannon/specs/")
- ✅ Search waves: search_nodes("shannon/waves/")
- ✅ Consistency = efficiency
Rule: Use protocol search patterns. Not creative queries.
Rationalization 4: "Create new entity for update"
Example: Agent creates "spec_002" to update "spec_001" instead of adding observations
COUNTER:
- ❌ NEVER create new entity to update existing entity
- ✅ Use add_observations for updates
- ✅ Creating duplicate entities = data chaos
- ✅ Example: WRONG: create_entities("spec_002"), RIGHT: add_observations("spec_001", ["new info"])
Rule: Updates use add_observations, not create_entities.
Rationalization 5: "Namespace collision unlikely"
Example: Agent creates "goal" entity in root namespace (not shannon/goals/)
COUNTER:
- ❌ NEVER create Shannon entities in root namespace
- ✅ shannon/* namespace prevents collision with user project entities
- ✅ User might have "goal" entity for their app -> collision = corruption
- ✅ shannon/goals/goal_001 = isolated, safe
Rule: shannon/* namespace mandatory. Prevents collisions.
Rationalization 6: "Manual filtering faster than search"
Example: Agent calls read_graph() then manually filters for waves
COUNTER:
- ❌ NEVER read full graph then filter manually
- ✅ Use search_nodes() with namespace prefix (efficient, targeted)
- ✅ read_graph() loads ENTIRE graph (100-1000+ entities)
- ✅ search_nodes("shannon/waves/") returns only waves (5-20 entities)
- ✅ Manual filtering = wasted tokens + time
Rule: Use search_nodes with namespace. Never read_graph for queries.
Detection Signal
If you're tempted to:
- Create entity without shannon/ prefix
- Skip creating relations
- Use custom search query
- Create new entity for update
- Use root namespace
- Read full graph then filter
Then you are rationalizing. Stop. Apply the protocol. Follow the rules.
When to Use
Use this skill when:
- Storing Shannon artifacts: Specs, waves, goals, checkpoints, SITREPs
- Querying Shannon history: "Show me all waves", "Find spec for this wave"
- Creating Shannon entities: Any Shannon data needs persistence
- Updating Shannon entities: Wave status change, checkpoint metadata update
- Establishing relations: Link wave to spec, checkpoint to wave, goal to spec
- Searching Shannon graph: Find entities by namespace, type, or timestamp
- Context preservation: Before wave transitions, session end, context limits
- SITREP coordination: Storing multi-agent progress reports
DO NOT use when:
- Storing user project data (use user namespace, not shannon/*)
- Non-Shannon workflows (generic Serena operations)
- Temporary data that doesn't need persistence
- Data that should be in project files instead of knowledge graph
Inputs
Required:
operation_type(string): Serena operation to perform- Options:
"create","read","update","search","relate","delete"
- Options:
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- Example:
"shannon/specs/spec_20250104_143022"
- Example:
search_pattern(string): For search operations- Example:
"shannon/waves/"(all waves) - Example:
"shannon/checkpoints/cp_20250104"(date-filtered)
- Example:
parent_entity(string): For create operations (establishes relation)- Example:
"shannon/specs/spec_001"(wave's parent)
- Example:
relation_type(string): For relate operations- Options:
"spawns","contains","tracks","created_checkpoint","implements","reports_on","relates_to"
- Options:
observations(array): For create/update operations- Example:
["type: spec_analysis", "created: 2025-01-04T14:30:22Z", "complexity_score: 0.68"]
- Example:
Core Competencies
1. Shannon Namespace Management
- Namespace Structure: shannon/specs/, shannon/waves/, shannon/goals/, shannon/checkpoints/, shannon/sitreps/
- Entity Naming: Standardized formats with timestamps or IDs
- Collision Prevention: shannon/* isolates Shannon entities from user project
- Queryability: Namespace prefix enables efficient targeted searches
- Organization: Clear hierarchy (specs -> waves -> tasks -> checkpoints)
2. Entity CRUD Operations
- Create: create_entities with shannon/* namespace, initial observations
- Read: search_nodes or open_nodes with specific entity names
- Update: add_observations to existing entities (NEVER create new entity)
- Delete: delete_entities (rare, only for cleanup or mistakes)
- Validation: Verify entity name format before creation
3. Relation Management
- Standard Relations: spawns, contains, tracks, created_checkpoint, implements, relates_to
- Mandatory Relations: EVERY entity connects to at least 1 other entity
- Relation Naming: Active voice (spec "spawns" wave, wave "contains" task)
- Bidirectional Context: Relations enable traversal (wave -> spec, checkpoint -> wave)
- Orphan Prevention: No standalone entities
4. Search Patterns
- Namespace Search: search_nodes("shannon/specs/") for all specs
- Specific Entity: open_nodes(["shannon/specs/spec_001"]) for exact entity
- Pattern Matching: search_nodes("shannon/waves/wave_2025") for date-filtered waves
- Never Full Graph: Avoid read_graph() except for full visualization
- Result Limits: Use search efficiently, narrow queries
5. Observation Management
- Initial Observations: Include type, creation_date, purpose, metadata
- Updates: add_observations for new information (status, progress, notes)
- No Duplicates: Never create new entity to update (use observations)
- Structured Data: Store JSON or key-value pairs in observations
- Timestamped: Include timestamp in observation content
Workflow
Step 1: Determine Entity Type
Input: Data to store (spec, wave, goal, checkpoint, SITREP)
Processing:
Identify entity type from data structure or user intent
- If ambiguous, check context:
- In spec analysis phase? -> shannon/specs/
- Tracking wave progress? -> shannon/waves/
- Setting goals? -> shannon/goals/
- If still unclear, ASK USER: "Should I store this as spec, wave, goal, or checkpoint?"
- NEVER default to root namespace or random name
- If ambiguous, check context:
Map to Shannon namespace:
- Specification -> shannon/specs/
- Wave -> shannon/waves/
- Goal -> shannon/goals/
- Checkpoint -> shannon/checkpoints/
- SITREP -> shannon/sitreps/
- Task -> shannon/tasks/ (usually nested under wave)
Generate timestamp (MANDATORY FORMAT):
- Format: YYYYMMdd_HHmmss
- Example: 20250104_143022 (2025-01-04 14:30:22)
- WHY: Sortable (alphabetical = chronological), consistent, query-safe
const timestamp = new Date().toISOString() .replace(/[-:]/g, '') .replace('T', '_') .split('.')[0]; // Result: 20250104_143022- NEVER use: ISO 8601 in name, human-readable dates, Unix timestamps
Sanitize entity name:
- Replace spaces with underscores: "E-commerce / Payment" -> "E-commerce_Payment"
- Remove forward slashes: "/" -> ""
- Lowercase: "Gateway" -> "gateway"
- Final: shannon/specs/e-commerce_payment_gateway_20250104_143022
- NEVER include spaces or "/" in entity names (breaks queries)
Output: Full entity name (e.g., shannon/specs/spec_20250104_143022)
Duration: 1 second
Step 2: Create Entity with Standard Format
Input: Entity name, entity type, data
Processing:
- Structure observations as list of strings:
[ "type: [entity_type]", "created: [ISO timestamp]", "purpose: [description]", "[key]: [value]", "[serialized JSON if complex data]" ] - Call create_entities:
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...}" ] }] }) - Verify creation successful
Output: Entity created, entity name
Duration: 2-3 seconds
Step 3: Create Mandatory Relations
Input: New entity name, related entities
Processing:
Identify parent or related entities:
- Spec -> None (root entity)
- Wave -> Spec (spawned from)
- Task -> Wave (contained in)
- Checkpoint -> Wave (created during)
- Goal -> Spec (implements)
- SITREP -> Wave (reports on)
Determine relation type (active voice) with VALIDATION: APPROVED RELATION TYPES:
- spawns (spec -> wave)
- contains (wave -> task)
- created_checkpoint (wave -> checkpoint)
- implements (goal -> spec)
- reports_on (sitrep -> wave)
- tracks (goal -> wave)
- relates_to (general purpose)
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
Step 4: Search Using Standard Patterns
Input: Query intent (e.g., "find all waves", "get spec_001", "list checkpoints")
Processing:
Map intent to search pattern:
- "All [type]" -> search_nodes("shannon/[type]s/")
- "Specific entity" -> open_nodes(["shannon/[type]s/[name]"])
- "Recent [type]" -> search_nodes("shannon/[type]s/[date_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/ prefixRULE: Always use FULL shannon/* path. Never partial match.
Parse results
Output: Matching entities with observations
Duration: 1-2 seconds
Step 5: Update via Observations
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:
- Create it first (if should exist)
- Report error to user (if unexpected)
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):
- Maximum ~100 observations per entity (guideline)
- If approaching limit, consider:
- Creating checkpoint entity (snapshot current state)
- Creating sub-entities (wave_001_phase2, wave_001_phase3)
- Archiving old observations (delete_observations)
- WHY: Large lists slow queries, hard to parse
- Better: Structured sub-entities with relations
Verify update successful
Output: Entity updated with new observations
Duration: 2-3 seconds
Step 6: Validate Graph Structure
Input: Recent operations
Processing:
Check entity naming:
- All Shannon entities have shannon/* prefix? ✅
- No typos in namespace (shannon/spec/ instead of shannon/specs/)? ✅
Check relations:
- Every new entity has >=1 relation? ✅
- Relations use active voice? ✅
- No orphaned entities? ✅
Check operations:
- Used add_observations for updates (not create_entities)? ✅
- Used search_nodes (not read_graph) for queries? ✅
- No duplicate entities? ✅
Output: Validation pass/fail, corrections if needed
Duration: 5 seconds
MCP Integration
Required MCPs
Serena MCP (MANDATORY)
- Purpose: Shannon's primary context preservation mechanism; stores all specs, waves, goals, checkpoints in persistent knowledge graph
- Usage:
// 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%"] }] }) - Fallback: NONE (Serena is mandatory for Shannon)
- Degradation: CRITICAL (Shannon cannot function without context preservation)
- Verification: Test with search_nodes("shannon/") - should return Shannon entities
Examples
Example 1: Store Spec Analysis
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
Example 2: Create Wave from Spec
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
Example 3: Query Wave History
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
Example 4: Update Wave Status
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
Example 5: Create Checkpoint with Relations
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
Outputs
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
}
}
Success Criteria
Successful when:
- ✅ All Shannon entities have shannon/* namespace prefix
- ✅ Entity names follow standard format (shannon/[type]s/[name]_[timestamp])
- ✅ Every entity has at least 1 relation (no orphans)
- ✅ Relations use active voice (spawns, contains, tracks)
- ✅ Updates use add_observations (not create_entities)
- ✅ Searches use namespace prefix (search_nodes("shannon/specs/"))
- ✅ No duplicate entities (same data in multiple entities)
- ✅ Graph structure supports lineage queries (checkpoint -> wave -> spec)
- ✅ Observations structured with timestamps and key-value pairs
- ✅ Validation confirms all protocols followed
Fails if:
- ❌ Entity created without shannon/ prefix (namespace violation)
- ❌ Entity created without relations (orphaned)
- ❌ Relations use passive voice or unclear naming
- ❌ Update creates new entity instead of add_observations (duplication)
- ❌ Search uses read_graph() for targeted query (inefficiency)
- ❌ Duplicate entities exist for same data
- ❌ Cannot trace lineage (broken relations)
- ❌ Observations unstructured or missing timestamps
- ❌ Namespace collision with user project entities
- ❌ Custom entity naming breaks conventions
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
Common Pitfalls
Pitfall 1: Missing shannon/ Prefix
Problem: Agent creates "spec_001" instead of "shannon/specs/spec_001"
Why It Fails:
- Namespace collision with user project entities (user might have "spec_001" entity)
- Cannot query all Shannon entities efficiently (search_nodes("shannon/") fails)
- Breaks Shannon isolation from project
Solution: ALWAYS prefix with shannon/[type]s/ (specs, waves, goals, checkpoints, sitreps)
Prevention: Validation rejects entities without shannon/ prefix
Pitfall 2: Orphaned Entities
Problem: Agent creates wave entity but forgets to link to parent spec
Why It Fails:
- Cannot trace wave -> spec lineage
- Cannot answer "which spec spawned this wave?"
- Context restoration impossible
Solution: EVERY entity MUST have >=1 relation (except root specs)
Prevention: Step 3 mandatory relation creation, validation checks
Pitfall 3: Update Creates Duplicate
Problem: Agent creates "spec_002" to update "spec_001" instead of adding observations
Why It Fails:
- Data duplication (two entities with overlapping information)
- Queries return multiple results (which is correct?)
- Graph pollution
Solution: Use add_observations for updates, NOT create_entities
Prevention: Skill emphasizes update protocol, anti-rationalization section
Pitfall 4: Inefficient Search
Problem: Agent calls read_graph() then manually filters for waves
Why It Fails:
- Loads entire graph (100-1000+ entities) when only need 5-20 waves
- Wastes tokens and time
- Unnecessary network traffic
Solution: Use search_nodes("shannon/waves/") for targeted query
Prevention: Step 4 search patterns, avoid read_graph() for queries
Pitfall 5: Inconsistent Entity Naming
Problem: Agent creates shannon/specs/spec_001, shannon/specs/specification_002, shannon/specs/my_spec_3
Why It Fails:
- Inconsistent patterns hard to query (search_nodes("shannon/specs/spec_") misses "specification_")
- Breaks naming conventions
- Confusion about entity type
Solution: Standardize: shannon/specs/spec_[timestamp] or shannon/specs/spec_[id]
Prevention: Step 1 entity naming protocol, examples show standard format
Pitfall 6: Missing Timestamps
Problem: Agent creates observations without timestamps (["status: complete", "progress: 100%"])
Why It Fails:
- Cannot determine WHEN update happened
- Cannot trace progress timeline
- Loses historical context
Solution: ALWAYS include timestamp in observations: ["updated: 2025-01-04T16:30:00Z", "status: complete"]
Prevention: Step 2 and Step 5 observation format includes timestamps
Validation
How to verify memory-coordination executed correctly:
Check Entity Names:
- search_nodes("shannon/") returns only Shannon entities ✅
- All entity names have shannon/[type]s/ prefix ✅
- No entities in root namespace with Shannon data ✅
Check Relations:
- Query entity -> Verify >=1 relation exists ✅
- Relations use active voice (spawns, contains, tracks) ✅
- Can trace lineage: checkpoint -> wave -> spec ✅
Check Operations:
- Updates used add_observations (not create_entities) ✅
- No duplicate entities (same data in multiple entities) ✅
- Searches used namespace prefix (not read_graph()) ✅
Check Observations:
- All observations have timestamps ✅
- Observations structured as key-value or JSON ✅
- Latest observations at end of list ✅
Test Queries:
- search_nodes("shannon/specs/") returns only specs ✅
- search_nodes("shannon/waves/") returns only waves ✅
- open_nodes(["shannon/specs/spec_001"]) returns specific spec ✅
- Queries execute in <2 seconds ✅
Test Lineage:
- Given checkpoint -> Can find parent wave ✅
- Given wave -> Can find parent spec ✅
- Given wave -> Can find all child tasks ✅
- Given spec -> Can find all spawned waves ✅
Progressive Disclosure
SKILL.md (This file): ~600 lines
- Overview, when to use, expected outcomes
- Anti-rationalization (6 violations with counters)
- 5 core competencies (namespace, CRUD, relations, search, observations)
- 6-step workflow (determine type, create, relate, search, update, validate)
- 5 examples (store spec, create wave, query history, update status, checkpoint)
- Success criteria, common pitfalls, validation
references/: No deep references needed (protocol is self-contained)
Claude loads references/ when: N/A (all protocol details in SKILL.md)
References
- Serena MCP documentation: https://github.com/cyanheads/serena-mcp
- Shannon context management: shannon-plugin/core/CONTEXT_MANAGEMENT.md
- Checkpoint protocols: shannon-plugin/skills/context-preservation/SKILL.md
- Wave orchestration: shannon-plugin/skills/wave-orchestration/SKILL.md
Metadata
Version: 4.0.0 Last Updated: 2025-11-04 Author: Shannon Framework Team License: MIT Status: Core (Protocol skill, mandatory for Serena MCP operations)