Problem Statement

Currently, Lattice uses YAML frontmatter as an intermediate checkpoint:

Document → Claude extracts → YAML frontmatter → lattice sync → FalkorDB

The frontmatter was implemented because Claude Code needs somewhere to write output. However:

  1. Users rarely review/edit the YAML before syncing
  2. The “human review” benefit is theoretical, not practical
  3. It adds complexity (two-step process, schema validation)
  4. Frontmatter clutters markdown files

Proposal: Remove frontmatter as a requirement. Entities go directly to FalkorDB.


Current Architecture

┌─────────────────────────────────────────────────────────────────────────┐
│ CURRENT: Two-Phase Flow │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ Phase 1: Entity Extraction (Claude Code) │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────┐ │
│ │ Document │────▶│ Claude │────▶│ YAML │ │
│ │ content │ │ /entity- │ │ frontmatter │ │
│ │ │ │ extract │ │ (in .md file) │ │
│ └─────────────┘ └─────────────┘ └────────┬────────┘ │
│ │ │
│ Phase 2: Graph Sync (Lattice CLI) │ │
│ ┌─────────────────────────────────────────────────▼────────┐ │
│ │ lattice sync │ │
│ │ - Read frontmatter from .md files │ │
│ │ - Validate schema │ │
│ │ - Upsert to FalkorDB │ │
│ │ - Generate embeddings │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────┘

Pain points:

  • Two commands needed (/entity-extract then /graph-sync)
  • Schema validation errors require re-editing frontmatter
  • Frontmatter bloats markdown files
  • Nobody actually reviews before sync

Proposed Architecture

┌─────────────────────────────────────────────────────────────────────────┐
│ PROPOSED: Single-Phase Flow │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ /graph-sync (Claude Code + Lattice CLI) │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────┐ │
│ │ Document │────▶│ Claude │────▶│ JSON output │ │
│ │ content │ │ extraction │ │ (structured) │ │
│ └─────────────┘ └─────────────┘ └────────┬────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────┐ │
│ │ Lattice CLI │ │
│ │ (pipes JSON │ │
│ │ to FalkorDB) │ │
│ └────────┬────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────┐ │
│ │ FalkorDB │ │
│ │ (source of │ │
│ │ truth) │ │
│ └─────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────┘

Implementation Options

Option A: Claude → JSON → CLI Pipe

Claude outputs structured JSON, CLI parses and syncs:

Terminal window
# New /graph-sync command workflow
claude "Extract entities from doc.md as JSON" | lattice ingest --stdin

Slash command:

# /graph-sync command
1. Run `lattice status` to find changed docs
2. For each doc:
- Read content
- Extract entities (output as JSON)
- Pipe to `lattice ingest` command
3. Report results

Claude output format:

{
"document": "docs/topic/file.md",
"title": "Document Title",
"summary": "2-3 sentence summary for embeddings",
"entities": [
{"name": "FalkorDB", "type": "Technology", "description": "..."}
],
"relationships": [
{"source": "Lattice", "relation": "USES", "target": "FalkorDB"}
]
}

New CLI command:

Terminal window
lattice ingest --stdin # Read JSON from stdin
lattice ingest --file extract.json # Read from file
lattice ingest --doc docs/file.md # Extract + ingest in one step

Option B: MCP Server for Direct Graph Access

Add FalkorDB as an MCP server, let Claude write directly:

// Claude could call MCP tools directly
mcp__falkordb__upsert_node({
label: "Technology",
name: "FalkorDB",
description: "Graph database"
})
mcp__falkordb__upsert_relationship({
source: "Lattice",
relation: "USES",
target: "FalkorDB"
})

Pros:

  • Simplest architecture (Claude → Graph directly)
  • No intermediate files or CLI commands

Cons:

  • Requires MCP server setup
  • Less control over batching/transactions
  • Harder to track what was synced

Option C: Hybrid - Optional Frontmatter

Keep frontmatter as optional, add direct sync:

Terminal window
lattice sync # Current: reads frontmatter
lattice sync --extract # New: Claude extracts + syncs directly
lattice sync --extract doc.md # Single doc, no frontmatter needed

Workflow:

# For reviewed docs (keep frontmatter)
/entity-extract doc.md
# Edit YAML if needed
lattice sync
# For bulk/trusted docs (skip frontmatter)
lattice sync --extract docs/

Why Option A?

FactorOption A (JSON)Option B (MCP)Option C (Hybrid)
ComplexityLowHigh (MCP setup)Medium
ControlHigh (CLI validates)Low (direct writes)High
DebuggingEasy (inspect JSON)HardMedium
RollbackRe-run extractionMessyMedium
Batch opsNaturalManualNatural

Implementation Plan

Phase 1: New CLI Command

Add lattice ingest command:

src/commands/ingest.command.ts
@Command({
name: 'ingest',
description: 'Ingest extracted entities from JSON'
})
export class IngestCommand {
@Option({
flags: '--stdin',
description: 'Read JSON from stdin'
})
stdin: boolean;
@Option({
flags: '--file <path>',
description: 'Read JSON from file'
})
file: string;
async run(): Promise<void> {
const json = this.stdin
? await this.readStdin()
: await this.readFile(this.file);
const data = JSON.parse(json);
await this.syncService.ingestExtraction(data);
}
}

Phase 2: Update Slash Commands

New /graph-sync command:

---
description: Extract entities and sync to graph (no frontmatter)
model: sonnet
---
## Process
1. Run `lattice status` to find docs needing sync
2. For each document:
a. Read document content
b. Extract entities as structured JSON:
```json
{
"document": "path/to/doc.md",
"title": "...",
"summary": "...",
"entities": [...],
"relationships": [...]
}
```
c. Write JSON to temp file
d. Run `lattice ingest --file /tmp/extract-{hash}.json`
3. Report results

Phase 3: Deprecate Frontmatter

  1. Keep frontmatter parsing for backward compatibility
  2. Add migration command: lattice migrate --to-graph
  3. Document new workflow as preferred

Schema Changes

Current: Frontmatter in Markdown

---
entities:
- name: FalkorDB
type: Technology
description: Graph database
relationships:
- source: this
relation: REFERENCES
target: FalkorDB
---

Proposed: JSON Extraction Format

{
"document": "docs/local-knowledge-graph/architecture.md",
"contentHash": "abc123",
"extraction": {
"title": "Knowledge Graph Architecture",
"summary": "Technical overview of the knowledge graph implementation...",
"entities": [
{
"name": "FalkorDB",
"type": "Technology",
"description": "Graph database with vector search"
}
],
"relationships": [
{
"source": "Lattice",
"relation": "USES",
"target": "FalkorDB"
}
]
},
"metadata": {
"extractedAt": "2025-11-29T09:30:00Z",
"extractedBy": "claude-sonnet-4"
}
}

What About Summary/Title?

Currently, summary in frontmatter is used for embeddings. Options:

Option 1: Extract Summary with Entities

Include in JSON extraction (recommended):

{
"document": "...",
"title": "Extracted from # heading or first line",
"summary": "AI-generated summary for embeddings",
"entities": [...]
}

Option 2: Minimal Frontmatter

Keep only non-entity fields:

---
created: 2025-11-29
updated: 2025-11-29
status: complete
topic: local-knowledge-graph
# No entities or relationships
---

Option 3: No Frontmatter at All

Derive everything from content:

  • Title: First # heading
  • Created/Updated: Git history
  • Topic: Directory name
  • Summary: AI-generated during extraction

Migration Path

For Existing Users

Terminal window
# 1. Export entities from frontmatter to graph
lattice migrate --frontmatter-to-graph
# 2. Optionally strip entities from frontmatter
lattice migrate --strip-frontmatter-entities
# 3. Use new workflow going forward
/graph-sync # Extracts and syncs directly

Backward Compatibility

  • lattice sync continues to work with frontmatter
  • New lattice ingest for JSON input
  • /entity-extract deprecated but still works

Trade-offs

What We Lose

Lost CapabilityImpactMitigation
Edit before syncLow (rarely used)Re-extract if wrong
Git history of entitiesMediumGraph has its own history
Audit trail in filesLowUse lattice history command
Offline entity inspectionMediumlattice export to JSON

What We Gain

New CapabilityImpact
Single commandHigh - simpler workflow
Cleaner markdownMedium - no YAML bloat
Faster syncMedium - no file I/O
Graph as truthHigh - single source

Open Questions

  1. Re-extraction on changes: If document content changes, should we re-extract automatically or require explicit command?

  2. Conflict resolution: If entity exists in graph but document changed, update or warn?

  3. Bulk operations: How to handle 100+ docs efficiently? Parallel Claude calls?

  4. Embedding generation: Still happens in CLI during ingest, or move to extraction phase?

  5. Validation: Where does schema validation happen? CLI or Claude?


Next Steps

  1. Implement lattice ingest command
  2. Create new /graph-sync slash command
  3. Test with 10-20 documents
  4. Add migration tooling
  5. Update documentation
  6. Deprecation timeline for frontmatter workflow

Conclusion

The frontmatter-free architecture simplifies Lattice by:

  1. Removing the intermediate checkpoint that users don’t actually use
  2. Making the graph the source of truth for entities
  3. Enabling single-command workflow (/graph-sync does everything)
  4. Keeping markdown files clean of entity metadata

The key insight: frontmatter was an implementation detail for Claude Code output, not a user feature. By using JSON as the transport format, we preserve Claude Code integration while eliminating unnecessary complexity.