Compare commits
3 Commits
d54599e27d
...
d340e06dad
| Author | SHA1 | Date | |
|---|---|---|---|
| d340e06dad | |||
| c5eccbb2a5 | |||
| d4ada9bedb |
@@ -1,46 +0,0 @@
|
||||
[2026-07-09 10:54:03.926] Hook called with args: ['/home/ptarrant/.claude/plugins/cache/claude-plugins-official/security-guidance/2.0.6/hooks/security_reminder_hook.py']
|
||||
[2026-07-09 10:54:03.929] Processing: hook_event=UserPromptSubmit, tool=
|
||||
[2026-07-09 10:56:09.126] Hook called with args: ['/home/ptarrant/.claude/plugins/cache/claude-plugins-official/security-guidance/2.0.6/hooks/security_reminder_hook.py']
|
||||
[2026-07-09 10:56:09.128] Processing: hook_event=PostToolUse, tool=Write
|
||||
[2026-07-09 10:56:18.474] Hook called with args: ['/home/ptarrant/.claude/plugins/cache/claude-plugins-official/security-guidance/2.0.6/hooks/security_reminder_hook.py']
|
||||
[2026-07-09 10:56:18.476] Processing: hook_event=PostToolUse, tool=Write
|
||||
[2026-07-09 10:56:21.852] Hook called with args: ['/home/ptarrant/.claude/plugins/cache/claude-plugins-official/security-guidance/2.0.6/hooks/security_reminder_hook.py']
|
||||
[2026-07-09 10:56:21.855] Processing: hook_event=PostToolUse, tool=Write
|
||||
[2026-07-09 10:56:25.336] Hook called with args: ['/home/ptarrant/.claude/plugins/cache/claude-plugins-official/security-guidance/2.0.6/hooks/security_reminder_hook.py']
|
||||
[2026-07-09 10:56:25.338] Processing: hook_event=PostToolUse, tool=Write
|
||||
[2026-07-09 10:56:28.741] Hook called with args: ['/home/ptarrant/.claude/plugins/cache/claude-plugins-official/security-guidance/2.0.6/hooks/security_reminder_hook.py']
|
||||
[2026-07-09 10:56:28.744] Processing: hook_event=PostToolUse, tool=Write
|
||||
[2026-07-09 10:56:32.070] Hook called with args: ['/home/ptarrant/.claude/plugins/cache/claude-plugins-official/security-guidance/2.0.6/hooks/security_reminder_hook.py']
|
||||
[2026-07-09 10:56:32.073] Processing: hook_event=PostToolUse, tool=Write
|
||||
[2026-07-09 10:56:35.419] Hook called with args: ['/home/ptarrant/.claude/plugins/cache/claude-plugins-official/security-guidance/2.0.6/hooks/security_reminder_hook.py']
|
||||
[2026-07-09 10:56:35.422] Processing: hook_event=PostToolUse, tool=Write
|
||||
[2026-07-09 10:56:39.157] Hook called with args: ['/home/ptarrant/.claude/plugins/cache/claude-plugins-official/security-guidance/2.0.6/hooks/security_reminder_hook.py']
|
||||
[2026-07-09 10:56:39.159] Processing: hook_event=PostToolUse, tool=Write
|
||||
[2026-07-09 10:56:42.516] Hook called with args: ['/home/ptarrant/.claude/plugins/cache/claude-plugins-official/security-guidance/2.0.6/hooks/security_reminder_hook.py']
|
||||
[2026-07-09 10:56:42.518] Processing: hook_event=PostToolUse, tool=Write
|
||||
[2026-07-09 10:56:48.542] Hook called with args: ['/home/ptarrant/.claude/plugins/cache/claude-plugins-official/security-guidance/2.0.6/hooks/security_reminder_hook.py']
|
||||
[2026-07-09 10:56:48.545] Processing: hook_event=PostToolUse, tool=Write
|
||||
[2026-07-09 10:56:51.814] Hook called with args: ['/home/ptarrant/.claude/plugins/cache/claude-plugins-official/security-guidance/2.0.6/hooks/security_reminder_hook.py']
|
||||
[2026-07-09 10:56:51.816] Processing: hook_event=PostToolUse, tool=Write
|
||||
[2026-07-09 10:56:55.095] Hook called with args: ['/home/ptarrant/.claude/plugins/cache/claude-plugins-official/security-guidance/2.0.6/hooks/security_reminder_hook.py']
|
||||
[2026-07-09 10:56:55.098] Processing: hook_event=PostToolUse, tool=Write
|
||||
[2026-07-09 10:56:59.075] Hook called with args: ['/home/ptarrant/.claude/plugins/cache/claude-plugins-official/security-guidance/2.0.6/hooks/security_reminder_hook.py']
|
||||
[2026-07-09 10:56:59.077] Processing: hook_event=PostToolUse, tool=Write
|
||||
[2026-07-09 10:57:02.336] Hook called with args: ['/home/ptarrant/.claude/plugins/cache/claude-plugins-official/security-guidance/2.0.6/hooks/security_reminder_hook.py']
|
||||
[2026-07-09 10:57:02.338] Processing: hook_event=PostToolUse, tool=Write
|
||||
[2026-07-09 10:57:05.616] Hook called with args: ['/home/ptarrant/.claude/plugins/cache/claude-plugins-official/security-guidance/2.0.6/hooks/security_reminder_hook.py']
|
||||
[2026-07-09 10:57:05.618] Processing: hook_event=PostToolUse, tool=Write
|
||||
[2026-07-09 10:57:08.886] Hook called with args: ['/home/ptarrant/.claude/plugins/cache/claude-plugins-official/security-guidance/2.0.6/hooks/security_reminder_hook.py']
|
||||
[2026-07-09 10:57:08.888] Processing: hook_event=PostToolUse, tool=Write
|
||||
[2026-07-09 10:57:12.207] Hook called with args: ['/home/ptarrant/.claude/plugins/cache/claude-plugins-official/security-guidance/2.0.6/hooks/security_reminder_hook.py']
|
||||
[2026-07-09 10:57:12.209] Processing: hook_event=PostToolUse, tool=Write
|
||||
[2026-07-09 10:57:16.216] Hook called with args: ['/home/ptarrant/.claude/plugins/cache/claude-plugins-official/security-guidance/2.0.6/hooks/security_reminder_hook.py']
|
||||
[2026-07-09 10:57:16.218] Processing: hook_event=PostToolUse, tool=Write
|
||||
[2026-07-09 10:57:19.540] Hook called with args: ['/home/ptarrant/.claude/plugins/cache/claude-plugins-official/security-guidance/2.0.6/hooks/security_reminder_hook.py']
|
||||
[2026-07-09 10:57:19.542] Processing: hook_event=PostToolUse, tool=Write
|
||||
[2026-07-09 10:57:31.383] Hook called with args: ['/home/ptarrant/.claude/plugins/cache/claude-plugins-official/security-guidance/2.0.6/hooks/security_reminder_hook.py']
|
||||
[2026-07-09 10:57:31.386] Processing: hook_event=PostToolUse, tool=Edit
|
||||
[2026-07-09 10:57:51.755] Hook called with args: ['/home/ptarrant/.claude/plugins/cache/claude-plugins-official/security-guidance/2.0.6/hooks/security_reminder_hook.py']
|
||||
[2026-07-09 10:57:51.758] Processing: hook_event=Stop, tool=
|
||||
[2026-07-09 10:57:51.761] _git_status_porcelain error: [Errno 138] emscripten does not support processes.
|
||||
[2026-07-09 10:57:51.761] Stop hook: empty review set
|
||||
@@ -1 +0,0 @@
|
||||
{"shown_warnings": [], "touched_paths": []}
|
||||
63
.gitignore
vendored
Normal file
63
.gitignore
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
# ─────────────────────────────────────────────
|
||||
# Godot 4.7 (client/)
|
||||
# ─────────────────────────────────────────────
|
||||
# Editor + import cache (4.x replaced .import/ with .godot/)
|
||||
.godot/
|
||||
# Exported builds
|
||||
/client/build/
|
||||
export.cfg
|
||||
# export_presets.cfg holds keystore paths / signing config — keep secrets out of history
|
||||
export_presets.cfg
|
||||
# Mono/C# (only if we drop to C# per charter §16)
|
||||
.mono/
|
||||
data_*/
|
||||
*.mono/
|
||||
|
||||
# ─────────────────────────────────────────────
|
||||
# Python / FastAPI (api/)
|
||||
# ─────────────────────────────────────────────
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
*.egg-info/
|
||||
.eggs/
|
||||
build/
|
||||
dist/
|
||||
# Virtual envs
|
||||
.venv/
|
||||
venv/
|
||||
env/
|
||||
ENV/
|
||||
# Tooling caches
|
||||
.pytest_cache/
|
||||
.mypy_cache/
|
||||
.ruff_cache/
|
||||
.coverage
|
||||
htmlcov/
|
||||
.tox/
|
||||
|
||||
# ─────────────────────────────────────────────
|
||||
# Secrets — the API key lives here in dev, NEVER in the client (charter §4)
|
||||
# ─────────────────────────────────────────────
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
|
||||
# ─────────────────────────────────────────────
|
||||
# Editors / OS
|
||||
# ─────────────────────────────────────────────
|
||||
.vscode/
|
||||
.idea/
|
||||
*.swp
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# ─────────────────────────────────────────────
|
||||
# Logs (charter §4/§10 logs go to a store, not the repo)
|
||||
# ─────────────────────────────────────────────
|
||||
*.log
|
||||
|
||||
# ─────────────────────────────────────────────
|
||||
# Claude Code harness session/state files
|
||||
# ─────────────────────────────────────────────
|
||||
.claude/
|
||||
12
CLAUDE.md
12
CLAUDE.md
@@ -530,3 +530,15 @@ Test that before building anything else. Every other system exists to make that
|
||||
- **When a request conflicts with this document, say so.** Do not silently comply. This file is the argument; if it is wrong, change the file first.
|
||||
- **When adding a system, state which side of §2 it falls on.** State or text. If it is both, it is two systems.
|
||||
- **Prefer deleting scope.** The POC's value is answering one question fast.
|
||||
|
||||
### Git workflow
|
||||
|
||||
The standard flow for this project. Claude follows it; the human owns `master`.
|
||||
|
||||
- **Branches.** `master` and `dev` are long-lived. `master` is release; `dev` is integration. All work branches off `dev`.
|
||||
- **Never commit non-doc changes directly to `master` or `dev`.** Anything that is not purely docs gets its own branch (`feature/…`, `fix/…`, `chore/…`, etc.), branched off `dev`.
|
||||
- **Doc-only edits may commit directly to `dev`** — no branch required.
|
||||
- **Never commit to `master`.** Ever. The human merges `dev` → `master` as they see fit. Claude never touches that merge.
|
||||
- **Merging a working branch → `dev`** happens only after the work is done, smoke-tested, and **the human confirms**. Merge locally with `--no-ff`.
|
||||
- **After merging to `dev`, delete the working branch locally.**
|
||||
- **Pushing.** Origin is set. Claude pushes **only `dev`**, and only after a merge. Never push working branches or `master` — the human always pushes `master`.
|
||||
|
||||
16
api/.dockerignore
Normal file
16
api/.dockerignore
Normal file
@@ -0,0 +1,16 @@
|
||||
# Keep the build context small and secrets out of the image.
|
||||
.env
|
||||
.env.*
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
.venv/
|
||||
venv/
|
||||
.pytest_cache/
|
||||
.mypy_cache/
|
||||
.ruff_cache/
|
||||
.coverage
|
||||
htmlcov/
|
||||
docs/
|
||||
README.md
|
||||
Dockerfile
|
||||
.dockerignore
|
||||
11
api/.env.example
Normal file
11
api/.env.example
Normal file
@@ -0,0 +1,11 @@
|
||||
# Copy to .env for local dev. NEVER commit the real .env. The client never sees
|
||||
# any of these — keys live only in the proxy (charter §4).
|
||||
|
||||
# Where the proxy sends model calls in dev (Ollama on the homelab).
|
||||
OLLAMA_BASE_URL=http://localhost:11434
|
||||
|
||||
# Prod model provider (charter §4). Leave blank in dev.
|
||||
REPLICATE_API_TOKEN=
|
||||
|
||||
# Port the proxy binds. compose / fly.io override this.
|
||||
PORT=8000
|
||||
26
api/Dockerfile
Normal file
26
api/Dockerfile
Normal file
@@ -0,0 +1,26 @@
|
||||
# /api — FastAPI proxy (charter §4). Docker-based for parity across
|
||||
# dev / homelab VPS / fly.io.
|
||||
FROM python:3.12-slim
|
||||
|
||||
# Faster, quieter Python in containers.
|
||||
ENV PYTHONUNBUFFERED=1 \
|
||||
PYTHONDONTWRITEBYTECODE=1 \
|
||||
PIP_NO_CACHE_DIR=1
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Install deps first so the layer caches when only app code changes.
|
||||
COPY requirements.txt .
|
||||
RUN pip install --no-cache-dir -r requirements.txt
|
||||
|
||||
# App code.
|
||||
COPY app ./app
|
||||
|
||||
# Run as non-root.
|
||||
RUN useradd --create-home --uid 1000 appuser
|
||||
USER appuser
|
||||
|
||||
EXPOSE 8000
|
||||
|
||||
# fly.io / compose set PORT; default to 8000 (charter localhost:8000).
|
||||
CMD ["sh", "-c", "uvicorn app.main:app --host 0.0.0.0 --port ${PORT:-8000}"]
|
||||
47
api/app/main.py
Normal file
47
api/app/main.py
Normal file
@@ -0,0 +1,47 @@
|
||||
"""FastAPI proxy entrypoint — the guarding proxy of charter §4.
|
||||
|
||||
Skeleton only: a health check plus the five role endpoints as stubs so the
|
||||
container runs and the client has something to point at. Real prompt routing,
|
||||
model selection, logging, and auth land later — all server-side (§4, §5).
|
||||
"""
|
||||
|
||||
from fastapi import FastAPI
|
||||
|
||||
app = FastAPI(title="coc-rpg proxy", version="0.0.1")
|
||||
|
||||
|
||||
@app.get("/health")
|
||||
def health() -> dict:
|
||||
"""Liveness probe for compose / fly.io."""
|
||||
return {"status": "ok"}
|
||||
|
||||
|
||||
# ── Role endpoints (charter §4) ──────────────────────────────────────────────
|
||||
# The client knows these paths and nothing about which model or prompt serves
|
||||
# them. Stubs for now; each will load its prompt from api/prompts/ and route to
|
||||
# the configured model.
|
||||
|
||||
|
||||
@app.post("/dm/narrate")
|
||||
def narrate() -> dict:
|
||||
return {"detail": "not implemented"}
|
||||
|
||||
|
||||
@app.post("/dm/adjudicate")
|
||||
def adjudicate() -> dict:
|
||||
return {"detail": "not implemented"}
|
||||
|
||||
|
||||
@app.post("/dm/improvise")
|
||||
def improvise() -> dict:
|
||||
return {"detail": "not implemented"}
|
||||
|
||||
|
||||
@app.post("/npc/speak")
|
||||
def npc_speak() -> dict:
|
||||
return {"detail": "not implemented"}
|
||||
|
||||
|
||||
@app.post("/party/banter")
|
||||
def banter() -> dict:
|
||||
return {"detail": "not implemented"}
|
||||
21
api/fly.toml
Normal file
21
api/fly.toml
Normal file
@@ -0,0 +1,21 @@
|
||||
# fly.io deploy config for the proxy (charter §4, prod). Stub — set app name and
|
||||
# region, then `fly deploy` from api/. Secrets (REPLICATE_API_TOKEN) go via
|
||||
# `fly secrets set`, never in this file.
|
||||
app = "coc-rpg-proxy" # TODO: claim a real app name
|
||||
primary_region = "ord" # TODO: pick a region
|
||||
|
||||
[build]
|
||||
dockerfile = "Dockerfile"
|
||||
|
||||
[http_service]
|
||||
internal_port = 8000
|
||||
force_https = true
|
||||
auto_stop_machines = true
|
||||
auto_start_machines = true
|
||||
min_machines_running = 0
|
||||
|
||||
[[http_service.checks]]
|
||||
method = "GET"
|
||||
path = "/health"
|
||||
interval = "15s"
|
||||
timeout = "2s"
|
||||
5
api/requirements.txt
Normal file
5
api/requirements.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
# FastAPI proxy runtime deps. Pinned from first resolve; bump deliberately.
|
||||
fastapi==0.139.0
|
||||
uvicorn[standard]==0.51.0
|
||||
httpx==0.28.1 # calling Ollama / Replicate
|
||||
pydantic==2.13.4 # request/response contracts
|
||||
17
docker-compose.yml
Normal file
17
docker-compose.yml
Normal file
@@ -0,0 +1,17 @@
|
||||
# Local dev — run the proxy in Docker with live reload.
|
||||
# docker compose up --build
|
||||
# Ollama runs on the homelab (charter §4), not here — point OLLAMA_BASE_URL at it.
|
||||
services:
|
||||
api:
|
||||
build: ./api
|
||||
ports:
|
||||
- "8000:8000"
|
||||
env_file:
|
||||
- ./api/.env
|
||||
environment:
|
||||
PORT: 8000
|
||||
# Mount source + reload so edits are live without a rebuild.
|
||||
volumes:
|
||||
- ./api/app:/app/app:ro
|
||||
command: >
|
||||
uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload
|
||||
Reference in New Issue
Block a user