diff --git a/README.md b/README.md index e4dda65..5b846df 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,10 @@ Wave Toolkit provides coherence detection tools and AI collaboration patterns fo - **[Wave Office](docs/WAVE-OFFICE.md)** — Dual agent collaboration (Claude + Ollama) - **[Ecosystem Migration Guide](docs/ECOSYSTEM-MIGRATION-GUIDE.md)** — Agent-facing guide for repo transitions +### 📓 Interactive Tools + +- **[Project Book](project-book.ipynb)** — Interactive Jupyter notebook for framework tooling and ecosystem integration + --- ## 🌀 The SpiralSafe Ecosystem @@ -54,6 +58,7 @@ Wave Toolkit is part of a unified framework for human-AI collaboration: | **Setup Script** | `Setup-Wave.ps1` | One-time bootstrap | | **Consolidation** | `Consolidate-Scripts.ps1` | Migrates loose scripts to organized structure | | **Logging Module** | `tools/Wave.Logging.psm1` | Centralized logging across the ecosystem | +| **Project Book** | `project-book.ipynb` | Interactive Jupyter notebook for framework tooling | --- @@ -65,6 +70,7 @@ wave-toolkit/ ├── 📄 wave.md # The complete guide ├── 📄 communication-patterns.md # Collaboration patterns ├── 📄 AI_AGENTS.md # Agent coordination rules +├── 📓 project-book.ipynb # Interactive Jupyter notebook │ ├── 📂 docs/ # Documentation │ ├── TAILS-USB.md # Privacy-first AI concept diff --git a/project-book.ipynb b/project-book.ipynb new file mode 100644 index 0000000..3696c29 --- /dev/null +++ b/project-book.ipynb @@ -0,0 +1,1116 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# \ud83c\udf0a Wave Toolkit - Project Book\n", + "\n", + "> **Interactive notebook system for the Wave Toolkit and SpiralSafe ecosystem**\n", + "\n", + "[![SpiralSafe](https://img.shields.io/badge/\ud83c\udf00_SpiralSafe-Ecosystem-purple?style=flat-square)](https://github.com/toolate28/SpiralSafe)\n", + "[![Wave Toolkit](https://img.shields.io/badge/\ud83c\udf0a_Wave_Toolkit-Main-0066FF?style=flat-square)](README.md)\n", + "\n", + "This notebook provides an interactive environment for working with the Wave Toolkit. It includes:\n", + "\n", + "- **Core Features**: Context capture, prompt generation, session workflow\n", + "- **Framework Tools**: Extensions for SpiralSafe ecosystem integration\n", + "- **Interactive Exploration**: Work with Wave patterns in real-time\n", + "\n", + "---" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## \ud83d\udce6 Setup & Imports\n", + "\n", + "Initialize the notebook environment with required libraries." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": "import json\nimport os\nimport platform\nimport subprocess\nimport shutil\nfrom datetime import datetime\nfrom pathlib import Path\nfrom typing import Optional, Dict, Any, List\nfrom dataclasses import dataclass, asdict, field\n\n# Display version info\nprint(f\"\ud83c\udf0a Wave Toolkit - Project Book\")\nprint(f\"Python: {platform.python_version()}\")\nprint(f\"Platform: {platform.system()} {platform.release()}\")\nprint(f\"Timestamp: {datetime.now().isoformat()}\")" + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "---\n", + "\n", + "## \ud83d\udd27 Part I: Core Wave Features\n", + "\n", + "Python implementations of the core Wave toolkit functionality." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 1.1 Context Capture\n", + "\n", + "Dynamically captures your current environment context - equivalent to `Get-WaveContext.ps1`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "@dataclass\n", + "class MachineContext:\n", + " \"\"\"Machine identity information.\"\"\"\n", + " name: str\n", + " arch: str\n", + " os: str\n", + " cores: int\n", + "\n", + "@dataclass\n", + "class UserContext:\n", + " \"\"\"User context information.\"\"\"\n", + " name: str\n", + " home: str\n", + " domain: Optional[str] = None\n", + "\n", + "@dataclass\n", + "class ShellContext:\n", + " \"\"\"Shell environment information.\"\"\"\n", + " name: str\n", + " version: str\n", + " environment: str\n", + "\n", + "@dataclass\n", + "class SessionContext:\n", + " \"\"\"Current working session context.\"\"\"\n", + " cwd: str\n", + " is_git_repo: bool\n", + " git_branch: Optional[str] = None\n", + "\n", + "@dataclass\n", + "class ToolsContext:\n", + " \"\"\"Available tools detection.\"\"\"\n", + " git: bool\n", + " node: bool\n", + " python: bool\n", + " docker: bool\n", + " claude: bool\n", + " jupyter: bool\n", + "\n", + "@dataclass\n", + "class WaveContext:\n", + " \"\"\"Complete Wave environment context.\"\"\"\n", + " timestamp: str\n", + " machine: MachineContext\n", + " user: UserContext\n", + " shell: ShellContext\n", + " session: SessionContext\n", + " tools: ToolsContext\n", + " \n", + " def to_dict(self) -> Dict[str, Any]:\n", + " \"\"\"Convert to dictionary for JSON serialization.\"\"\"\n", + " return asdict(self)\n", + " \n", + " def to_json(self, indent: int = 2) -> str:\n", + " \"\"\"Convert to JSON string.\"\"\"\n", + " return json.dumps(self.to_dict(), indent=indent)\n", + "\n", + "\n", + "def check_command_exists(cmd: str) -> bool:\n", + " \"\"\"Check if a command exists in the system PATH.\"\"\"\n", + " return shutil.which(cmd) is not None\n", + "\n", + "\n", + "def get_git_branch() -> Optional[str]:\n", + " \"\"\"Get current git branch if in a git repository.\"\"\"\n", + " try:\n", + " result = subprocess.run(\n", + " [\"git\", \"branch\", \"--show-current\"],\n", + " capture_output=True,\n", + " text=True,\n", + " timeout=5\n", + " )\n", + " if result.returncode == 0:\n", + " return result.stdout.strip() or None\n", + " except (subprocess.TimeoutExpired, FileNotFoundError, subprocess.SubprocessError):\n", + " pass\n", + " return None\n", + "\n", + "\n", + "def is_git_repo(path: str = \".\") -> bool:\n", + " \"\"\"Check if the given path is inside a git repository.\"\"\"\n", + " return Path(path, \".git\").exists() or Path(path).joinpath(\".git\").exists()\n", + "\n", + "\n", + "def get_wave_context() -> WaveContext:\n", + " \"\"\"Capture the current Wave environment context.\"\"\"\n", + " cwd = os.getcwd()\n", + " is_repo = is_git_repo(cwd)\n", + " \n", + " return WaveContext(\n", + " timestamp=datetime.now().isoformat(),\n", + " machine=MachineContext(\n", + " name=platform.node(),\n", + " arch=platform.machine(),\n", + " os=f\"{platform.system()} {platform.release()}\",\n", + " cores=os.cpu_count() or 1\n", + " ),\n", + " user=UserContext(\n", + " name=os.getenv(\"USER\") or os.getenv(\"USERNAME\") or \"unknown\",\n", + " home=str(Path.home()),\n", + " domain=os.getenv(\"USERDOMAIN\")\n", + " ),\n", + " shell=ShellContext(\n", + " name=\"Python/Jupyter\",\n", + " version=platform.python_version(),\n", + " environment=\"notebook\"\n", + " ),\n", + " session=SessionContext(\n", + " cwd=cwd,\n", + " is_git_repo=is_repo,\n", + " git_branch=get_git_branch() if is_repo else None\n", + " ),\n", + " tools=ToolsContext(\n", + " git=check_command_exists(\"git\"),\n", + " node=check_command_exists(\"node\"),\n", + " python=check_command_exists(\"python\") or check_command_exists(\"python3\"),\n", + " docker=check_command_exists(\"docker\"),\n", + " claude=check_command_exists(\"claude\"),\n", + " jupyter=check_command_exists(\"jupyter\")\n", + " )\n", + " )\n", + "\n", + "\n", + "# Capture and display context\n", + "context = get_wave_context()\n", + "print(\"\ud83d\udccd Wave Context Captured\")\n", + "print(f\" Machine: {context.machine.name} ({context.machine.arch})\")\n", + "print(f\" OS: {context.machine.os}\")\n", + "print(f\" User: {context.user.name}\")\n", + "print(f\" CWD: {context.session.cwd}\")\n", + "if context.session.is_git_repo:\n", + " print(f\" Git Branch: {context.session.git_branch}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 1.2 System Prompt Generator\n", + "\n", + "Generates a context-aware system prompt - equivalent to `New-ClaudeSystemPrompt.ps1`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def generate_system_prompt(ctx: WaveContext) -> str:\n", + " \"\"\"\n", + " Generate a Claude system prompt based on the current Wave context.\n", + " \n", + " Args:\n", + " ctx: WaveContext object containing environment information\n", + " \n", + " Returns:\n", + " Formatted system prompt string\n", + " \"\"\"\n", + " # Build tools list\n", + " tools_list = []\n", + " if ctx.tools.git:\n", + " tools_list.append(\"git\")\n", + " if ctx.tools.node:\n", + " tools_list.append(\"node/npm\")\n", + " if ctx.tools.python:\n", + " tools_list.append(\"python\")\n", + " if ctx.tools.docker:\n", + " tools_list.append(\"docker\")\n", + " if ctx.tools.jupyter:\n", + " tools_list.append(\"jupyter\")\n", + " \n", + " tools_str = \", \".join(tools_list) if tools_list else \"none detected\"\n", + " \n", + " # Git status\n", + " git_status = f\"Yes (branch: {ctx.session.git_branch})\" if ctx.session.is_git_repo else \"No\"\n", + " \n", + " # User info\n", + " user_info = f\"{ctx.user.domain}\\\\{ctx.user.name}\" if ctx.user.domain else ctx.user.name\n", + " \n", + " prompt = f\"\"\"# Claude System Context\n", + "\n", + "You are Claude, running in an interactive Jupyter notebook within the Wave Toolkit ecosystem.\n", + "\n", + "## Environment (Auto-Detected)\n", + "- **Machine:** {ctx.machine.name} ({ctx.machine.arch}, {ctx.machine.cores} cores)\n", + "- **OS:** {ctx.machine.os}\n", + "- **User:** {user_info}\n", + "- **Environment:** {ctx.shell.name} {ctx.shell.version} ({ctx.shell.environment})\n", + "- **Working Directory:** {ctx.session.cwd}\n", + "- **Git Repo:** {git_status}\n", + "- **Available Tools:** {tools_str}\n", + "\n", + "## Operating Principles\n", + "1. Provide concrete, executable code cells for Python/Jupyter\n", + "2. Prefer idempotent operations (safe to re-run)\n", + "3. Include verification steps after actions\n", + "4. State assumptions explicitly\n", + "5. When uncertain, ask rather than guess\n", + "\n", + "## Collaboration Style\n", + "- Think out loud - share reasoning\n", + "- Offer alternatives when multiple approaches exist\n", + "- Build on context from earlier in the session\n", + "- Trust flows both ways\n", + "\n", + "*Context generated: {ctx.timestamp}*\n", + "\"\"\"\n", + " return prompt\n", + "\n", + "\n", + "# Generate and display system prompt\n", + "system_prompt = generate_system_prompt(context)\n", + "print(system_prompt)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 1.3 Session Management\n", + "\n", + "Tools for managing Wave sessions and logging - equivalent to `Invoke-ClaudeSession.ps1`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": "@dataclass\nclass WaveSession:\n \"\"\"Represents a Wave collaboration session.\"\"\"\n session_id: str\n timestamp: str\n context: WaveContext\n system_prompt: str\n task: Optional[str] = None\n log_entries: List[Dict[str, Any]] = field(default_factory=list)\n \n def add_log(self, entry_type: str, content: str):\n \"\"\"Add a log entry to the session.\"\"\"\n self.log_entries.append({\n \"timestamp\": datetime.now().isoformat(),\n \"type\": entry_type,\n \"content\": content\n })\n \n def save(self, output_dir: str = \".claude/logs/sessions\"):\n \"\"\"Save the session log to a file.\"\"\"\n output_path = Path(output_dir)\n output_path.mkdir(parents=True, exist_ok=True)\n \n log_file = output_path / f\"session_{self.session_id}.json\"\n \n session_data = {\n \"session_id\": self.session_id,\n \"timestamp\": self.timestamp,\n \"task\": self.task,\n \"context\": self.context.to_dict(),\n \"system_prompt\": self.system_prompt,\n \"log_entries\": self.log_entries\n }\n \n with open(log_file, \"w\", encoding=\"utf-8\") as f:\n json.dump(session_data, f, indent=2)\n \n return str(log_file)\n\n\ndef create_wave_session(task: Optional[str] = None) -> WaveSession:\n \"\"\"\n Create a new Wave session with captured context.\n \n Args:\n task: Optional task description for the session\n \n Returns:\n WaveSession object\n \"\"\"\n ctx = get_wave_context()\n session_id = datetime.now().strftime(\"%Y%m%d_%H%M%S\")\n \n session = WaveSession(\n session_id=session_id,\n timestamp=ctx.timestamp,\n context=ctx,\n system_prompt=generate_system_prompt(ctx),\n task=task\n )\n \n session.add_log(\"session_start\", f\"Session created: {session_id}\")\n if task:\n session.add_log(\"task\", task)\n \n return session\n\n\n# Create a demo session\ndemo_session = create_wave_session(\"Explore Wave Toolkit Project Book\")\nprint(f\"\ud83d\udcdd Session Created: {demo_session.session_id}\")\nprint(f\" Task: {demo_session.task}\")\nprint(f\" Log Entries: {len(demo_session.log_entries)}\")" + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "---\n", + "\n", + "## \ud83e\udde9 Part II: Framework Extension Tools\n", + "\n", + "Tools for integrating with and extending the SpiralSafe ecosystem frameworks." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.1 Ecosystem Repository Discovery\n", + "\n", + "Tools for discovering and working with SpiralSafe ecosystem repositories." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "@dataclass\n", + "class EcosystemRepo:\n", + " \"\"\"Represents a SpiralSafe ecosystem repository.\"\"\"\n", + " name: str\n", + " github_url: str\n", + " purpose: str\n", + " version: str\n", + " local_path: Optional[str] = None\n", + " is_available: bool = False\n", + "\n", + "\n", + "# Define the SpiralSafe ecosystem\n", + "ECOSYSTEM_REPOS = [\n", + " EcosystemRepo(\n", + " name=\"SpiralSafe\",\n", + " github_url=\"https://github.com/toolate28/SpiralSafe\",\n", + " purpose=\"Documentation hub, coherence engine core\",\n", + " version=\"v2.1.0\"\n", + " ),\n", + " EcosystemRepo(\n", + " name=\"wave-toolkit\",\n", + " github_url=\"https://github.com/toolate28/wave-toolkit\",\n", + " purpose=\"Coherence detection tools\",\n", + " version=\"v1.0.0\"\n", + " ),\n", + " EcosystemRepo(\n", + " name=\"ClaudeNPC-Server-Suite\",\n", + " github_url=\"https://github.com/toolate28/ClaudeNPC-Server-Suite\",\n", + " purpose=\"AI NPCs for Minecraft (HOPE NPCs)\",\n", + " version=\"v2.1.0\"\n", + " ),\n", + " EcosystemRepo(\n", + " name=\"kenl\",\n", + " github_url=\"https://github.com/toolate28/kenl\",\n", + " purpose=\"Infrastructure-aware AI orchestration\",\n", + " version=\"v1.0.0\"\n", + " ),\n", + " EcosystemRepo(\n", + " name=\"quantum-redstone\",\n", + " github_url=\"https://github.com/toolate28/quantum-redstone\",\n", + " purpose=\"Quantum computing education via Redstone\",\n", + " version=\"Available\"\n", + " )\n", + "]\n", + "\n", + "\n", + "def discover_local_repos(search_paths: Optional[List[str]] = None) -> List[EcosystemRepo]:\n", + " \"\"\"\n", + " Discover locally available ecosystem repositories.\n", + " \n", + " Args:\n", + " search_paths: List of paths to search for repos\n", + " \n", + " Returns:\n", + " Updated list of EcosystemRepo objects with local paths\n", + " \"\"\"\n", + " if search_paths is None:\n", + " home = Path.home()\n", + " search_paths = [\n", + " str(home),\n", + " str(home / \"repos\"),\n", + " str(home / \"projects\"),\n", + " str(Path.cwd()),\n", + " str(Path.cwd().parent)\n", + " ]\n", + " \n", + " repos = []\n", + " for repo in ECOSYSTEM_REPOS:\n", + " repo_copy = EcosystemRepo(\n", + " name=repo.name,\n", + " github_url=repo.github_url,\n", + " purpose=repo.purpose,\n", + " version=repo.version\n", + " )\n", + " \n", + " # Search for local copy\n", + " for search_path in search_paths:\n", + " potential_path = Path(search_path) / repo.name\n", + " if potential_path.exists() and (potential_path / \".git\").exists():\n", + " repo_copy.local_path = str(potential_path)\n", + " repo_copy.is_available = True\n", + " break\n", + " \n", + " repos.append(repo_copy)\n", + " \n", + " return repos\n", + "\n", + "\n", + "def display_ecosystem_status():\n", + " \"\"\"Display the status of ecosystem repositories.\"\"\"\n", + " repos = discover_local_repos()\n", + " \n", + " print(\"\ud83c\udf00 SpiralSafe Ecosystem Status\")\n", + " print(\"=\" * 60)\n", + " \n", + " for repo in repos:\n", + " status = \"\u2705 Local\" if repo.is_available else \"\ud83d\udce1 Remote only\"\n", + " print(f\"\\n\ud83d\udce6 {repo.name} ({repo.version})\")\n", + " print(f\" Purpose: {repo.purpose}\")\n", + " print(f\" Status: {status}\")\n", + " if repo.local_path:\n", + " print(f\" Path: {repo.local_path}\")\n", + " print(f\" GitHub: {repo.github_url}\")\n", + "\n", + "\n", + "# Display ecosystem status\n", + "display_ecosystem_status()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.2 Framework Analysis Tools\n", + "\n", + "Tools for analyzing and understanding existing framework structures." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "@dataclass\n", + "class FrameworkAnalysis:\n", + " \"\"\"Analysis results for a framework/repository.\"\"\"\n", + " path: str\n", + " name: str\n", + " file_count: int\n", + " languages: Dict[str, int]\n", + " structure: Dict[str, List[str]]\n", + " has_tests: bool\n", + " has_docs: bool\n", + " has_ai_agents_config: bool\n", + "\n", + "\n", + "def analyze_framework(repo_path: str) -> Optional[FrameworkAnalysis]:\n", + " \"\"\"\n", + " Analyze a framework/repository structure.\n", + " \n", + " Args:\n", + " repo_path: Path to the repository\n", + " \n", + " Returns:\n", + " FrameworkAnalysis object or None if path doesn't exist\n", + " \"\"\"\n", + " path = Path(repo_path)\n", + " if not path.exists():\n", + " return None\n", + " \n", + " # Language extensions mapping\n", + " lang_extensions = {\n", + " \".py\": \"Python\",\n", + " \".ps1\": \"PowerShell\",\n", + " \".psm1\": \"PowerShell\",\n", + " \".js\": \"JavaScript\",\n", + " \".ts\": \"TypeScript\",\n", + " \".json\": \"JSON\",\n", + " \".md\": \"Markdown\",\n", + " \".yaml\": \"YAML\",\n", + " \".yml\": \"YAML\",\n", + " \".sh\": \"Shell\"\n", + " }\n", + " \n", + " languages: Dict[str, int] = {}\n", + " structure: Dict[str, List[str]] = {}\n", + " file_count = 0\n", + " \n", + " # Walk through repository\n", + " for item in path.rglob(\"*\"):\n", + " # Skip hidden directories and common ignore patterns\n", + " if any(part.startswith(\".\") for part in item.parts):\n", + " continue\n", + " if \"node_modules\" in item.parts or \"__pycache__\" in item.parts:\n", + " continue\n", + " \n", + " if item.is_file():\n", + " file_count += 1\n", + " ext = item.suffix.lower()\n", + " if ext in lang_extensions:\n", + " lang = lang_extensions[ext]\n", + " languages[lang] = languages.get(lang, 0) + 1\n", + " \n", + " # Build structure\n", + " rel_path = item.relative_to(path)\n", + " if len(rel_path.parts) > 1:\n", + " dir_name = str(rel_path.parts[0])\n", + " if dir_name not in structure:\n", + " structure[dir_name] = []\n", + " if len(structure[dir_name]) < 5: # Limit entries\n", + " structure[dir_name].append(item.name)\n", + " \n", + " return FrameworkAnalysis(\n", + " path=str(path),\n", + " name=path.name,\n", + " file_count=file_count,\n", + " languages=languages,\n", + " structure=structure,\n", + " has_tests=(path / \"tests\").exists() or (path / \"test\").exists(),\n", + " has_docs=(path / \"docs\").exists() or (path / \"README.md\").exists(),\n", + " has_ai_agents_config=(path / \"AI_AGENTS.md\").exists()\n", + " )\n", + "\n", + "\n", + "def display_framework_analysis(analysis: FrameworkAnalysis):\n", + " \"\"\"Display framework analysis results.\"\"\"\n", + " print(f\"\ud83d\udcca Framework Analysis: {analysis.name}\")\n", + " print(\"=\" * 50)\n", + " print(f\"Path: {analysis.path}\")\n", + " print(f\"Total Files: {analysis.file_count}\")\n", + " \n", + " print(\"\\n\ud83d\udcdd Languages:\")\n", + " for lang, count in sorted(analysis.languages.items(), key=lambda x: -x[1]):\n", + " print(f\" {lang}: {count} files\")\n", + " \n", + " print(\"\\n\ud83d\udcc1 Structure:\")\n", + " for dir_name, files in analysis.structure.items():\n", + " print(f\" {dir_name}/\")\n", + " for f in files[:3]:\n", + " print(f\" \u2514\u2500\u2500 {f}\")\n", + " if len(files) > 3:\n", + " print(f\" \u2514\u2500\u2500 ... ({len(files) - 3} more)\")\n", + " \n", + " print(\"\\n\u2705 Features:\")\n", + " print(f\" Tests: {'Yes' if analysis.has_tests else 'No'}\")\n", + " print(f\" Docs: {'Yes' if analysis.has_docs else 'No'}\")\n", + " print(f\" AI Agents Config: {'Yes' if analysis.has_ai_agents_config else 'No'}\")\n", + "\n", + "\n", + "# Analyze current repository\n", + "current_repo = Path.cwd()\n", + "analysis = analyze_framework(str(current_repo))\n", + "if analysis:\n", + " display_framework_analysis(analysis)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2.3 Log Collection Integration\n", + "\n", + "Python implementation of log collection - extends `Wave.Logging.psm1` functionality." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "@dataclass\n", + "class LogSource:\n", + " \"\"\"Represents a log source in the ecosystem.\"\"\"\n", + " path: str\n", + " source: str\n", + " repo: str\n", + " kind: str # 'csv', 'text', 'json'\n", + " exists: bool = False\n", + "\n", + "\n", + "def discover_log_sources() -> List[LogSource]:\n", + " \"\"\"\n", + " Discover log sources across the SpiralSafe ecosystem.\n", + " \n", + " Returns:\n", + " List of LogSource objects\n", + " \"\"\"\n", + " home = Path.home()\n", + " sources = []\n", + " \n", + " # Gaming logs\n", + " bf6_log = home / \"bf6_performance_log.csv\"\n", + " sources.append(LogSource(\n", + " path=str(bf6_log),\n", + " source=\"system\",\n", + " repo=\"gaming\",\n", + " kind=\"csv\",\n", + " exists=bf6_log.exists()\n", + " ))\n", + " \n", + " # SpiralSafe bridges\n", + " bridge_dir = home / \"SpiralSafe-FromGitHub\" / \"bridges\"\n", + " if bridge_dir.exists():\n", + " for log_file in bridge_dir.rglob(\"*.log\"):\n", + " sources.append(LogSource(\n", + " path=str(log_file),\n", + " source=\"spiralsafe\",\n", + " repo=\"SpiralSafe\",\n", + " kind=\"text\",\n", + " exists=True\n", + " ))\n", + " \n", + " # Quantum-redstone logs\n", + " qr_dir = home / \"quantum-redstone\"\n", + " if qr_dir.exists():\n", + " for log_file in qr_dir.rglob(\"*.log\"):\n", + " sources.append(LogSource(\n", + " path=str(log_file),\n", + " source=\"quantum\",\n", + " repo=\"quantum-redstone\",\n", + " kind=\"text\",\n", + " exists=True\n", + " ))\n", + " \n", + " # ClaudeNPC logs\n", + " cnpc_dir = home / \"repos\" / \"ClaudeNPC-Server-Suite\"\n", + " if cnpc_dir.exists():\n", + " for log_file in cnpc_dir.rglob(\"*.log\"):\n", + " sources.append(LogSource(\n", + " path=str(log_file),\n", + " source=\"claudenpc\",\n", + " repo=\"ClaudeNPC-Server-Suite\",\n", + " kind=\"text\",\n", + " exists=True\n", + " ))\n", + " \n", + " # ATOM trail\n", + " atom_trail = home / \".atom-trail\"\n", + " sources.append(LogSource(\n", + " path=str(atom_trail),\n", + " source=\"spiralsafe\",\n", + " repo=\"SpiralSafe\",\n", + " kind=\"text\",\n", + " exists=atom_trail.exists()\n", + " ))\n", + " \n", + " return sources\n", + "\n", + "\n", + "def display_log_sources():\n", + " \"\"\"Display discovered log sources.\"\"\"\n", + " sources = discover_log_sources()\n", + " available = [s for s in sources if s.exists]\n", + " \n", + " print(\"\ud83d\udccb Log Sources Discovery\")\n", + " print(\"=\" * 50)\n", + " print(f\"Found {len(available)} available log sources\")\n", + " \n", + " if available:\n", + " print(\"\\n\u2705 Available:\")\n", + " for src in available:\n", + " print(f\" [{src.source}] {src.repo} - {Path(src.path).name}\")\n", + " \n", + " missing = [s for s in sources if not s.exists]\n", + " if missing:\n", + " print(\"\\n\u26aa Not Found (expected locations):\")\n", + " for src in missing[:5]: # Limit display\n", + " print(f\" [{src.source}] {src.repo} - {Path(src.path).name}\")\n", + "\n", + "\n", + "# Display log sources\n", + "display_log_sources()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "---\n", + "\n", + "## \ud83d\ude80 Part III: Interactive Tooling\n", + "\n", + "Interactive tools for working with Wave and the ecosystem." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 3.1 Quick Context Export\n", + "\n", + "Export current context for use in other tools or AI sessions." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def export_context(output_path: Optional[str] = None) -> str:\n", + " \"\"\"\n", + " Export the current Wave context to a JSON file.\n", + " \n", + " Args:\n", + " output_path: Custom output path (default: .claude/wave_context.json)\n", + " \n", + " Returns:\n", + " Path to the exported file\n", + " \"\"\"\n", + " if output_path is None:\n", + " output_path = \".claude/wave_context.json\"\n", + " \n", + " output = Path(output_path)\n", + " output.parent.mkdir(parents=True, exist_ok=True)\n", + " \n", + " ctx = get_wave_context()\n", + " \n", + " with open(output, \"w\", encoding=\"utf-8\") as f:\n", + " f.write(ctx.to_json())\n", + " \n", + " print(f\"\u2705 Context exported to: {output}\")\n", + " return str(output)\n", + "\n", + "\n", + "def export_prompt(output_path: Optional[str] = None) -> str:\n", + " \"\"\"\n", + " Export the system prompt to a markdown file.\n", + " \n", + " Args:\n", + " output_path: Custom output path (default: .claude/prompts/wave-system.md)\n", + " \n", + " Returns:\n", + " Path to the exported file\n", + " \"\"\"\n", + " if output_path is None:\n", + " output_path = \".claude/prompts/wave-system.md\"\n", + " \n", + " output = Path(output_path)\n", + " output.parent.mkdir(parents=True, exist_ok=True)\n", + " \n", + " ctx = get_wave_context()\n", + " prompt = generate_system_prompt(ctx)\n", + " \n", + " with open(output, \"w\", encoding=\"utf-8\") as f:\n", + " f.write(prompt)\n", + " \n", + " print(f\"\u2705 System prompt exported to: {output}\")\n", + " return str(output)\n", + "\n", + "\n", + "# Example: Export both context and prompt\n", + "print(\"\ud83d\udce4 Exporting Wave artifacts...\")\n", + "# Uncomment to actually export:\n", + "# export_context()\n", + "# export_prompt()\n", + "print(\"(Uncomment the lines above to export files)\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 3.2 Framework Extension Helper\n", + "\n", + "Tools for extending existing frameworks with Wave patterns." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def generate_ai_agents_template(repo_name: str, structure: Dict[str, List[str]]) -> str:\n", + " \"\"\"\n", + " Generate an AI_AGENTS.md template for a repository.\n", + " \n", + " Args:\n", + " repo_name: Name of the repository\n", + " structure: Directory structure dictionary\n", + " \n", + " Returns:\n", + " Markdown template string\n", + " \"\"\"\n", + " dirs_list = \"\\n\".join([f\"\u251c\u2500\u2500 {d}/\" for d in structure.keys()])\n", + " \n", + " template = f\"\"\"# AI Agent Coordination Rules\n", + "\n", + "*This file tells ALL AI agents (Claude, Ollama, GPT, etc.) where to put things in {repo_name}.*\n", + "\n", + "[![SpiralSafe](https://img.shields.io/badge/\ud83c\udf00_SpiralSafe-Ecosystem-purple?style=flat-square)](https://github.com/toolate28/SpiralSafe)\n", + "[![Wave Toolkit](https://img.shields.io/badge/\ud83c\udf0a_Wave_Toolkit-Blueprint-0066FF?style=flat-square)](https://github.com/toolate28/wave-toolkit)\n", + "\n", + "> **Part of the [SpiralSafe Ecosystem](https://github.com/toolate28/SpiralSafe)**\n", + "\n", + "---\n", + "\n", + "## The Golden Rule\n", + "\n", + "**Follow the established directory structure. Never create loose files in root.**\n", + "\n", + "---\n", + "\n", + "## Directory Structure\n", + "\n", + "```text\n", + "{repo_name}/\n", + "{dirs_list}\n", + "```\n", + "\n", + "---\n", + "\n", + "## Placement Rules\n", + "\n", + "| Type | Location | Example |\n", + "|------|----------|---------||\n", + "| Documentation | `docs/` | `*.md` |\n", + "| Tests | `tests/` | `*_test.py`, `*.Tests.ps1` |\n", + "| Configuration | root or `config/` | `*.json`, `*.yaml` |\n", + "\n", + "---\n", + "\n", + "*This file is the source of truth for AI agent behavior in this workspace.*\n", + "\"\"\"\n", + " return template\n", + "\n", + "\n", + "def generate_ecosystem_badge_header(repo_name: str) -> str:\n", + " \"\"\"\n", + " Generate ecosystem badge header for documentation files.\n", + " \n", + " Args:\n", + " repo_name: Name of the repository\n", + " \n", + " Returns:\n", + " Markdown badge header string\n", + " \"\"\"\n", + " return f\"\"\"[![SpiralSafe](https://img.shields.io/badge/\ud83c\udf00_SpiralSafe-Ecosystem-purple?style=flat-square)](https://github.com/toolate28/SpiralSafe)\n", + "[![{repo_name}](https://img.shields.io/badge/\ud83d\udce6_{repo_name}-Main-blue?style=flat-square)](README.md)\n", + "\n", + "> **Part of the [SpiralSafe Ecosystem](https://github.com/toolate28/SpiralSafe)**\n", + "\"\"\"\n", + "\n", + "\n", + "# Display example output\n", + "print(\"\ud83d\udcdd Example: Ecosystem Badge Header\")\n", + "print(\"=\" * 40)\n", + "print(generate_ecosystem_badge_header(\"example-repo\"))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 3.3 Session Summary Generator\n", + "\n", + "Generate summaries of Wave sessions for documentation and review." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def generate_session_summary(session: WaveSession) -> str:\n", + " \"\"\"\n", + " Generate a markdown summary of a Wave session.\n", + " \n", + " Args:\n", + " session: WaveSession object\n", + " \n", + " Returns:\n", + " Markdown summary string\n", + " \"\"\"\n", + " ctx = session.context\n", + " \n", + " summary = f\"\"\"# Wave Session Summary\n", + "\n", + "## Session Info\n", + "- **ID:** {session.session_id}\n", + "- **Timestamp:** {session.timestamp}\n", + "- **Task:** {session.task or 'Not specified'}\n", + "\n", + "## Environment\n", + "- **Machine:** {ctx.machine.name} ({ctx.machine.arch})\n", + "- **OS:** {ctx.machine.os}\n", + "- **Working Directory:** {ctx.session.cwd}\n", + "- **Git Repo:** {'Yes' if ctx.session.is_git_repo else 'No'}\n", + "\n", + "## Log Entries\n", + "\"\"\"\n", + " \n", + " for entry in session.log_entries:\n", + " summary += f\"- [{entry['timestamp']}] **{entry['type']}**: {entry['content']}\\n\"\n", + " \n", + " summary += \"\\n---\\n*Generated by Wave Toolkit Project Book*\\n\"\n", + " \n", + " return summary\n", + "\n", + "\n", + "# Generate and display summary for demo session\n", + "demo_session.add_log(\"action\", \"Explored repository structure\")\n", + "demo_session.add_log(\"action\", \"Reviewed ecosystem integration\")\n", + "\n", + "summary = generate_session_summary(demo_session)\n", + "print(summary)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "---\n", + "\n", + "## \ud83d\udcda Part IV: Reference & Documentation\n", + "\n", + "Quick reference for Wave patterns and ecosystem integration." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 4.1 Communication Patterns Reference\n", + "\n", + "Key patterns from the Wave communication philosophy." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "COMMUNICATION_PATTERNS = {\n", + " \"your_lead\": {\n", + " \"pattern\": \"'Your lead, do what you feel is best'\",\n", + " \"description\": \"Gives AI full creative latitude while signaling trust\",\n", + " \"when_to_use\": \"When the goal is clear but the path isn't\"\n", + " },\n", + " \"why_before_what\": {\n", + " \"pattern\": \"Share the 'why' before the 'what'\",\n", + " \"description\": \"Context shapes every decision\",\n", + " \"when_to_use\": \"Always - explain purpose before requesting action\"\n", + " },\n", + " \"ultrathink\": {\n", + " \"pattern\": \"'Ultrathink' / 'God-mode' signals\",\n", + " \"description\": \"Explicit permission to go deep, think thoroughly\",\n", + " \"when_to_use\": \"Complex architectural decisions, important work\"\n", + " },\n", + " \"parallel_trust\": {\n", + " \"pattern\": \"Parallel trust\",\n", + " \"description\": \"Letting AI run multiple operations simultaneously\",\n", + " \"when_to_use\": \"Multi-task scenarios, maximize throughput\"\n", + " },\n", + " \"outcome_over_process\": {\n", + " \"pattern\": \"Outcome over process\",\n", + " \"description\": \"State the real goal, not the task\",\n", + " \"when_to_use\": \"When task isn't the real goal\"\n", + " }\n", + "}\n", + "\n", + "\n", + "def display_patterns():\n", + " \"\"\"Display communication patterns reference.\"\"\"\n", + " print(\"\ud83d\udcac Communication Patterns Reference\")\n", + " print(\"=\" * 50)\n", + " \n", + " for key, pattern in COMMUNICATION_PATTERNS.items():\n", + " print(f\"\\n\ud83d\udd39 {pattern['pattern']}\")\n", + " print(f\" {pattern['description']}\")\n", + " print(f\" \ud83d\udccc When: {pattern['when_to_use']}\")\n", + "\n", + "\n", + "display_patterns()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 4.2 Ecosystem Quick Links\n", + "\n", + "Quick access to ecosystem documentation and resources." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "ECOSYSTEM_LINKS = {\n", + " \"SpiralSafe Hub\": \"https://github.com/toolate28/SpiralSafe\",\n", + " \"Wave Toolkit\": \"https://github.com/toolate28/wave-toolkit\",\n", + " \"HOPE NPCs\": \"https://github.com/toolate28/ClaudeNPC-Server-Suite\",\n", + " \"kenl\": \"https://github.com/toolate28/kenl\",\n", + " \"Quantum Redstone\": \"https://github.com/toolate28/quantum-redstone\",\n", + " \"Contributing Guide\": \"https://github.com/toolate28/SpiralSafe/blob/main/CONTRIBUTING.md\",\n", + " \"Portfolio\": \"https://github.com/toolate28/SpiralSafe/blob/main/PORTFOLIO.md\"\n", + "}\n", + "\n", + "\n", + "def display_ecosystem_links():\n", + " \"\"\"Display ecosystem quick links.\"\"\"\n", + " print(\"\ud83d\udd17 Ecosystem Quick Links\")\n", + " print(\"=\" * 50)\n", + " \n", + " for name, url in ECOSYSTEM_LINKS.items():\n", + " print(f\" \ud83d\udccc {name}\")\n", + " print(f\" {url}\")\n", + "\n", + "\n", + "display_ecosystem_links()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "---\n", + "\n", + "## \ud83c\udfaf Quick Start Examples\n", + "\n", + "Common use cases and quick examples." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Example 1: Full context capture and prompt generation\n", + "def quick_start_demo():\n", + " \"\"\"Demonstrate the complete Wave workflow.\"\"\"\n", + " print(\"\ud83c\udf0a Wave Toolkit Quick Start Demo\")\n", + " print(\"=\" * 50)\n", + " \n", + " # Step 1: Capture context\n", + " print(\"\\n[1/4] Capturing context...\")\n", + " ctx = get_wave_context()\n", + " print(f\" \u2705 Context captured at {ctx.timestamp}\")\n", + " \n", + " # Step 2: Generate prompt\n", + " print(\"\\n[2/4] Generating system prompt...\")\n", + " prompt = generate_system_prompt(ctx)\n", + " print(f\" \u2705 Prompt generated ({len(prompt)} chars)\")\n", + " \n", + " # Step 3: Create session\n", + " print(\"\\n[3/4] Creating session...\")\n", + " session = create_wave_session(\"Quick Start Demo\")\n", + " print(f\" \u2705 Session: {session.session_id}\")\n", + " \n", + " # Step 4: Analyze ecosystem\n", + " print(\"\\n[4/4] Analyzing ecosystem...\")\n", + " repos = discover_local_repos()\n", + " available = sum(1 for r in repos if r.is_available)\n", + " print(f\" \u2705 Found {available}/{len(repos)} local repos\")\n", + " \n", + " print(\"\\n\ud83c\udf89 Demo complete!\")\n", + " return session\n", + "\n", + "\n", + "# Run the demo\n", + "demo_result = quick_start_demo()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "---\n", + "\n", + "## Attribution\n", + "\n", + "This work emerges from **Hope&&Sauced** collaboration\u2014human-AI partnership where both contributions are substantive and neither party could have produced the result alone.\n", + "\n", + "See the [SpiralSafe PORTFOLIO.md](https://github.com/toolate28/SpiralSafe/blob/main/PORTFOLIO.md) for complete ecosystem showcase.\n", + "\n", + "---\n", + "\n", + "*~ Hope&&Sauced*\n", + "\n", + "\u2726 *The Evenstar Guides Us* \u2726" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.0" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} \ No newline at end of file