Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .claude/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
"hooks": [
{
"type": "command",
"command": "python \"C:\\Users\\idean\\Downloads\\Forge V3\\tools\\notify.py\" --done"
"command": "python tools/notify.py --done"
}
]
}
Expand All @@ -30,7 +30,7 @@
"hooks": [
{
"type": "command",
"command": "python \"C:\\Users\\idean\\Downloads\\Forge V3\\tools\\notify.py\" --input"
"command": "python tools/notify.py --input"
}
]
}
Expand All @@ -40,7 +40,7 @@
"hooks": [
{
"type": "command",
"command": "python \"C:\\Users\\idean\\Downloads\\Forge V3\\tools\\notify.py\" --input"
"command": "python tools/notify.py --input"
}
]
}
Expand All @@ -51,7 +51,7 @@
"hooks": [
{
"type": "command",
"command": "python \"C:\\Users\\idean\\Downloads\\Forge V3\\tools\\notify.py\" --input"
"command": "python tools/notify.py --input"
}
]
}
Expand Down
92 changes: 92 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# Forge V3 - Claude Code Instructions

## Project Overview

Forge V3 is an Institutional Memory Engine - a cognitive architecture platform for persistent organizational knowledge with AI-powered governance, compliance frameworks, and blockchain integration.

## Architecture

- **Backend**: Python 3.11+ with FastAPI (3 API services on ports 8001-8003)
- **Frontend**: React 19 + TypeScript + Vite + Tailwind v4
- **Database**: Neo4j (graph + vector)
- **Caching**: Redis (optional)

## Key Directories

```
forge-cascade-v2/ # Main backend service
├── forge/ # Core Python package
│ ├── api/ # FastAPI routes
│ ├── models/ # Pydantic models
│ ├── repositories/ # Data access layer
│ ├── services/ # Business logic
│ └── security/ # Auth & tokens
├── frontend/ # React dashboard
└── tests/ # Test suite

forge_virtuals_integration/ # Blockchain integration
contracts/ # Solidity smart contracts
marketplace/ # Marketplace frontend
```

## Commit Messages

Use standard conventional commits without AI attribution:

```
type: short description

Optional longer description explaining the "why" not the "what".
```

Types: `fix`, `feat`, `refactor`, `test`, `docs`, `chore`

Do NOT include:
- Co-Authored-By lines for AI assistants
- "Generated with" attribution
- Automated tooling credits

## Code Style

- Python: Follow existing patterns, use type hints, Pydantic for models
- Use `pathlib.Path` for cross-platform file paths
- Platform-specific code must handle both Windows and Linux

## Testing

```bash
cd forge-cascade-v2
pytest # Run all tests
pytest -x # Stop on first failure
pytest tests/test_api/ # Run specific directory
```

## Running Locally

```bash
# Activate virtual environment (from project root)
source env/bin/activate

# Start all servers
cd forge-cascade-v2
python start_all_servers.py

# Or individually
python -m uvicorn forge.api.app:app --port 8001 # Cascade API
python run_compliance.py # Compliance API
python run_virtuals.py # Virtuals API
```

## Environment

Copy `.env.example` to `.env` and configure:
- `NEO4J_URI`, `NEO4J_USERNAME`, `NEO4J_PASSWORD` - Database
- `JWT_SECRET_KEY` - Auth (min 32 chars)
- `REDIS_URL` - Optional caching

## Cross-Platform Notes

This project supports both Windows and Linux. When writing code:
- Use `pathlib.Path` instead of string paths
- Use `sys.platform` or `platform.system()` for OS-specific logic
- Never hardcode absolute paths
40 changes: 28 additions & 12 deletions forge-cascade-v2/start_all_servers.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,14 +85,24 @@ def start_server(name: str, config: dict) -> subprocess.Popen | None:

print(f" Starting {config['name']} on port {port}...")

# Build platform-specific subprocess arguments
# Windows: use creationflags for process group
# Linux/Mac: use start_new_session for process group
popen_kwargs = {
"cwd": config["cwd"],
"stdout": subprocess.PIPE,
"stderr": subprocess.PIPE,
}

if sys.platform == "win32":
popen_kwargs["creationflags"] = subprocess.CREATE_NEW_PROCESS_GROUP
else:
# On Unix-like systems, start_new_session creates a new process group
# This allows us to use os.killpg() to terminate all child processes
popen_kwargs["start_new_session"] = True

# Start the process
process = subprocess.Popen(
config["command"],
cwd=config["cwd"],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
creationflags=subprocess.CREATE_NEW_PROCESS_GROUP if sys.platform == "win32" else 0,
)
process = subprocess.Popen(config["command"], **popen_kwargs)

# Wait for it to become healthy
if wait_for_server(config["health_url"], timeout=30):
Expand All @@ -110,11 +120,17 @@ def stop_all():
for name, process in processes.items():
if process and process.poll() is None:
print(f" Stopping {SERVERS[name]['name']}...")
if sys.platform == "win32":
process.terminate()
else:
os.killpg(os.getpgid(process.pid), signal.SIGTERM)
process.wait(timeout=5)
try:
if sys.platform == "win32":
process.terminate()
else:
# On Unix-like systems, kill the entire process group
# This ensures all child processes are terminated
os.killpg(os.getpgid(process.pid), signal.SIGTERM)
process.wait(timeout=5)
except (ProcessLookupError, OSError) as e:
# Process may have already terminated
print(f" Note: Process already terminated or error: {e}")
print("All servers stopped.")


Expand Down
5 changes: 4 additions & 1 deletion test_auth_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@
import asyncio
import os
import sys
from pathlib import Path

# Set up environment variables before importing
os.environ.setdefault("EMBEDDING_PROVIDER", "mock")
os.environ.setdefault("LLM_PROVIDER", "mock")

sys.path.insert(0, 'C:\\Users\\idean\\Downloads\\Forge V3\\forge-cascade-v2')
# Add forge-cascade-v2 to path (cross-platform)
script_dir = Path(__file__).parent.absolute()
sys.path.insert(0, str(script_dir / 'forge-cascade-v2'))

from forge.config import get_settings
from forge.database.client import Neo4jClient
Expand Down