Initial commit

This commit is contained in:
Zhongwei Li
2025-11-30 08:46:50 +08:00
commit a3a73d67d7
67 changed files with 19703 additions and 0 deletions

View File

@@ -0,0 +1,396 @@
#!/usr/bin/env python3
"""
Oracle Context Generation Script
Generate context summaries from Oracle knowledge base for injection into
claude.md, session starts, or specific tasks.
Usage:
python generate_context.py --session-start
python generate_context.py --task "implement API"
python generate_context.py --output claude.md
python generate_context.py --tier 1
Examples:
python generate_context.py --session-start
python generate_context.py --task "database migration" --tier 2
python generate_context.py --output ../claude.md --update
"""
import os
import sys
import json
import argparse
from datetime import datetime
from pathlib import Path
def find_oracle_root():
"""Find the .oracle directory."""
current = Path.cwd()
while current != current.parent:
oracle_path = current / '.oracle'
if oracle_path.exists():
return oracle_path
current = current.parent
return None
def load_all_knowledge(oracle_path):
"""Load all knowledge from Oracle."""
knowledge_dir = oracle_path / 'knowledge'
all_knowledge = []
for category in ['patterns', 'preferences', 'gotchas', 'solutions', 'corrections']:
file_path = knowledge_dir / f'{category}.json'
if file_path.exists():
with open(file_path, 'r') as f:
entries = json.load(f)
for entry in entries:
entry['_category'] = category
all_knowledge.append(entry)
return all_knowledge
def filter_by_tier(knowledge, tier=1):
"""Filter knowledge by tier level."""
if tier == 1:
# Critical only - always load
return [k for k in knowledge if k.get('priority') in ['critical', 'high']]
elif tier == 2:
# Medium priority - load on relevance
return [k for k in knowledge if k.get('priority') in ['critical', 'high', 'medium']]
else:
# All knowledge
return knowledge
def filter_by_relevance(knowledge, task_description):
"""Filter knowledge relevant to a specific task."""
if not task_description:
return knowledge
task_lower = task_description.lower()
relevant = []
for entry in knowledge:
# Check if task keywords appear in entry
score = 0
if task_lower in entry.get('title', '').lower():
score += 3
if task_lower in entry.get('content', '').lower():
score += 2
if task_lower in entry.get('context', '').lower():
score += 1
# Check tags
for tag in entry.get('tags', []):
if tag.lower() in task_lower or task_lower in tag.lower():
score += 2
if score > 0:
entry['_relevance_score'] = score
relevant.append(entry)
# Sort by relevance
return sorted(relevant, key=lambda x: x.get('_relevance_score', 0), reverse=True)
def get_recent_corrections(oracle_path, limit=5):
"""Get most recent corrections."""
knowledge_dir = oracle_path / 'knowledge'
corrections_file = knowledge_dir / 'corrections.json'
if not corrections_file.exists():
return []
with open(corrections_file, 'r') as f:
corrections = json.load(f)
# Sort by creation date
sorted_corrections = sorted(
corrections,
key=lambda x: x.get('created', ''),
reverse=True
)
return sorted_corrections[:limit]
def generate_session_start_context(oracle_path):
"""Generate context for session start."""
knowledge = load_all_knowledge(oracle_path)
# Tier 1: Critical items
critical_items = filter_by_tier(knowledge, tier=1)
# Recent corrections
recent_corrections = get_recent_corrections(oracle_path, limit=5)
context = """# Oracle Project Knowledge
*Auto-generated context for this session*
"""
# Project Overview
index_file = oracle_path / 'index.json'
if index_file.exists():
with open(index_file, 'r') as f:
index = json.load(f)
context += f"""## Project Status
- Total Knowledge Entries: {index.get('total_entries', 0)}
- Last Updated: {index.get('last_updated', 'Unknown')}
- Sessions Recorded: {len(index.get('sessions', []))}
"""
# Critical Knowledge
if critical_items:
context += "## [WARNING] Critical Knowledge\n\n"
for item in critical_items[:10]: # Top 10
context += f"### {item.get('title', 'Untitled')}\n\n"
context += f"**Category**: {item['_category'].capitalize()} | **Priority**: {item.get('priority', 'N/A')}\n\n"
context += f"{item.get('content', 'No content')}\n\n"
if item.get('context'):
context += f"*When to apply*: {item['context']}\n\n"
context += "---\n\n"
# Recent Corrections
if recent_corrections:
context += "## Recent Corrections (Learn from these!)\n\n"
for correction in recent_corrections:
context += f"- **{correction.get('title', 'Correction')}**\n"
context += f" {correction.get('content', '')}\n"
if correction.get('context'):
context += f" *Context*: {correction['context']}\n"
context += "\n"
context += f"\n*Generated: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}*\n"
return context
def generate_task_context(oracle_path, task_description):
"""Generate context for a specific task."""
knowledge = load_all_knowledge(oracle_path)
# Filter by relevance to task
relevant = filter_by_relevance(knowledge, task_description)
context = f"""# Oracle Context for: {task_description}
*Relevant knowledge from Oracle*
"""
if not relevant:
context += "No specific knowledge found for this task.\n\n"
context += "This might be a new area - remember to record learnings!\n"
return context
context += f"Found {len(relevant)} relevant knowledge entries.\n\n"
# Group by category
by_category = {}
for item in relevant[:20]: # Top 20 most relevant
category = item['_category']
if category not in by_category:
by_category[category] = []
by_category[category].append(item)
# Format by category
category_names = {
'patterns': ' Patterns',
'preferences': ' Preferences',
'gotchas': '[WARNING] Gotchas',
'solutions': '[OK] Solutions',
'corrections': ' Corrections'
}
for category, items in by_category.items():
context += f"## {category_names.get(category, category.capitalize())}\n\n"
for item in items:
context += f"### {item.get('title', 'Untitled')}\n\n"
context += f"{item.get('content', 'No content')}\n\n"
if item.get('examples'):
context += "**Examples**:\n"
for ex in item['examples']:
context += f"- {ex}\n"
context += "\n"
context += "---\n\n"
context += f"\n*Generated: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}*\n"
return context
def generate_compact_context(oracle_path):
"""Generate compact context for claude.md injection."""
knowledge = load_all_knowledge(oracle_path)
critical = [k for k in knowledge if k.get('priority') == 'critical']
high = [k for k in knowledge if k.get('priority') == 'high']
context = "<!-- ORACLE_CONTEXT_START -->\n"
context += "<!-- Auto-generated by Oracle - Do not edit manually -->\n\n"
if critical:
context += "**Critical Knowledge**:\n"
for item in critical[:5]:
context += f"- {item.get('title', 'Untitled')}\n"
context += "\n"
if high:
context += "**Important Patterns**:\n"
for item in high[:5]:
context += f"- {item.get('title', 'Untitled')}\n"
context += "\n"
# Recent corrections
recent_corrections = get_recent_corrections(oracle_path, limit=3)
if recent_corrections:
context += "**Recent Learnings**:\n"
for correction in recent_corrections:
content = correction.get('content', '')
# Extract just the "right" part if it's a correction
if '[CHECK] Right:' in content:
right_part = content.split('[CHECK] Right:')[1].split('\n')[0].strip()
context += f"- {right_part}\n"
else:
context += f"- {correction.get('title', '')}\n"
context += "\n"
context += f"*Updated: {datetime.now().strftime('%Y-%m-%d %H:%M')}*\n"
context += "<!-- ORACLE_CONTEXT_END -->\n"
return context
def update_claude_md(oracle_path, project_path):
"""Update claude.md with Oracle context."""
claude_md = project_path / 'claude.md'
context = generate_compact_context(oracle_path)
if not claude_md.exists():
# Create new claude.md with Oracle section
content = f"""# Project Documentation
## Project Knowledge (Oracle)
{context}
## Additional Context
[Add your project-specific context here]
"""
with open(claude_md, 'w') as f:
f.write(content)
print(f"[OK] Created new claude.md with Oracle context")
return
# Update existing claude.md
with open(claude_md, 'r') as f:
content = f.read()
# Replace Oracle section if it exists
if '<!-- ORACLE_CONTEXT_START -->' in content:
import re
pattern = r'<!-- ORACLE_CONTEXT_START -->.*?<!-- ORACLE_CONTEXT_END -->'
content = re.sub(pattern, context, content, flags=re.DOTALL)
print(f"[OK] Updated Oracle context in claude.md")
else:
# Add Oracle section at the top
content = f"## Project Knowledge (Oracle)\n\n{context}\n\n{content}"
print(f"[OK] Added Oracle context to claude.md")
with open(claude_md, 'w') as f:
f.write(content)
def main():
parser = argparse.ArgumentParser(
description='Generate Oracle context summaries',
formatter_class=argparse.RawDescriptionHelpFormatter
)
parser.add_argument(
'--session-start',
action='store_true',
help='Generate context for session start'
)
parser.add_argument(
'--task',
help='Generate context for specific task'
)
parser.add_argument(
'--tier',
type=int,
choices=[1, 2, 3],
default=1,
help='Context tier level (1=critical, 2=medium, 3=all)'
)
parser.add_argument(
'--output',
help='Output file (default: stdout)'
)
parser.add_argument(
'--update',
action='store_true',
help='Update the output file (for claude.md)'
)
args = parser.parse_args()
# Find Oracle
oracle_path = find_oracle_root()
if not oracle_path:
print("[ERROR] Error: .oracle directory not found.")
sys.exit(1)
# Generate context
if args.session_start:
context = generate_session_start_context(oracle_path)
elif args.task:
context = generate_task_context(oracle_path, args.task)
elif args.update and args.output:
project_path = oracle_path.parent
update_claude_md(oracle_path, project_path)
return
else:
context = generate_compact_context(oracle_path)
# Output
if args.output:
output_path = Path(args.output)
with open(output_path, 'w') as f:
f.write(context)
print(f"[OK] Context written to: {output_path}")
else:
print(context)
if __name__ == '__main__':
main()