Initialize project structure with core files, environment settings, and basic configurations
Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
5
.vscode/settings.json
vendored
Normal file
5
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"chat.tools.terminal.autoApprove": {
|
||||
"New-Item": true
|
||||
}
|
||||
}
|
||||
8
charactergarden/.env
Normal file
8
charactergarden/.env
Normal file
@@ -0,0 +1,8 @@
|
||||
NODE_ENV=development
|
||||
APP_PORT=3000
|
||||
FRONTEND_PORT=5173
|
||||
DB_PATH=/data/sqlite/app.db
|
||||
|
||||
# Optional — only needed when running with the llm profile
|
||||
OLLAMA_URL=http://ollama:11434
|
||||
OLLAMA_MODEL=llama3
|
||||
11
charactergarden/.env.example
Normal file
11
charactergarden/.env.example
Normal file
@@ -0,0 +1,11 @@
|
||||
# Copy this file to .env and adjust values as needed.
|
||||
# Never commit .env — it is gitignored.
|
||||
|
||||
NODE_ENV=development
|
||||
APP_PORT=3000
|
||||
FRONTEND_PORT=5173
|
||||
DB_PATH=/data/sqlite/app.db
|
||||
|
||||
# Optional — only required when running with: docker compose --profile llm up
|
||||
OLLAMA_URL=http://ollama:11434
|
||||
OLLAMA_MODEL=llama3
|
||||
33
charactergarden/.gitignore
vendored
Normal file
33
charactergarden/.gitignore
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
# ── Dependencies ────────────────────────────────────────────
|
||||
node_modules/
|
||||
|
||||
# ── TypeScript build output ──────────────────────────────────
|
||||
app/dist/
|
||||
frontend/dist/
|
||||
|
||||
# ── Vite cache ───────────────────────────────────────────────
|
||||
frontend/.vite/
|
||||
|
||||
# ── SQLite database (keep the directory, not the data) ───────
|
||||
data/sqlite/*.db
|
||||
data/sqlite/*.db-shm
|
||||
data/sqlite/*.db-wal
|
||||
|
||||
# ── Environment — commit .env.example, never .env ────────────
|
||||
.env
|
||||
.env.local
|
||||
.env.*.local
|
||||
|
||||
# ── Docker volumes / build context artifacts ─────────────────
|
||||
.docker/
|
||||
|
||||
# ── OS noise ─────────────────────────────────────────────────
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
desktop.ini
|
||||
|
||||
# ── Editor noise ─────────────────────────────────────────────
|
||||
.vscode/settings.json
|
||||
.idea/
|
||||
*.suo
|
||||
*.user
|
||||
22
charactergarden/app/package.json
Normal file
22
charactergarden/app/package.json
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"name": "charactergarden-app",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "ts-node-dev --respawn src/index.ts",
|
||||
"build": "tsc",
|
||||
"start": "node dist/index.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"fastify": "^4.28.1",
|
||||
"better-sqlite3": "^9.6.0",
|
||||
"uuid": "^9.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/better-sqlite3": "^7.6.11",
|
||||
"@types/node": "^20.14.0",
|
||||
"@types/uuid": "^9.0.8",
|
||||
"ts-node-dev": "^2.0.0",
|
||||
"typescript": "^5.4.5"
|
||||
}
|
||||
}
|
||||
76
charactergarden/app/src/types.ts
Normal file
76
charactergarden/app/src/types.ts
Normal file
@@ -0,0 +1,76 @@
|
||||
// Core contracts — DO NOT modify without updating project.md
|
||||
|
||||
// ── Section 2.1 ─────────────────────────────────────────────
|
||||
export interface Entity {
|
||||
id: string;
|
||||
type: string;
|
||||
name: string;
|
||||
attributes: Record<string, unknown>;
|
||||
}
|
||||
|
||||
// ── Section 2.2 ─────────────────────────────────────────────
|
||||
export const ALLOWED_VERBS = [
|
||||
"move",
|
||||
"open",
|
||||
"close",
|
||||
"take",
|
||||
"drop",
|
||||
"use",
|
||||
"inspect",
|
||||
"speak",
|
||||
] as const;
|
||||
|
||||
export type Verb = (typeof ALLOWED_VERBS)[number];
|
||||
|
||||
export interface Action {
|
||||
actor: string; // entity id
|
||||
verb: Verb;
|
||||
target?: string; // entity id
|
||||
params?: Record<string, unknown>;
|
||||
}
|
||||
|
||||
// ── Section 2.3 ─────────────────────────────────────────────
|
||||
export interface ValidationResult {
|
||||
accepted: Action[];
|
||||
rejected: { action: Action; reason: string }[];
|
||||
state_changes: StateChange[];
|
||||
}
|
||||
|
||||
// ── Section 2.4 ─────────────────────────────────────────────
|
||||
export interface StateChange {
|
||||
entity_id: string;
|
||||
field: string;
|
||||
old_value: unknown;
|
||||
new_value: unknown;
|
||||
}
|
||||
|
||||
// ── Section 2.5 ─────────────────────────────────────────────
|
||||
export interface GameEvent {
|
||||
id: string;
|
||||
turn: number;
|
||||
action: Action;
|
||||
result: "success" | "fail";
|
||||
timestamp: number;
|
||||
}
|
||||
|
||||
// ── Section 4 — Memory types ─────────────────────────────────
|
||||
export interface Turn {
|
||||
id: string;
|
||||
turn: number;
|
||||
input: string;
|
||||
output: string;
|
||||
timestamp: number;
|
||||
}
|
||||
|
||||
export interface Belief {
|
||||
entity_id: string;
|
||||
claim: string;
|
||||
confidence: number;
|
||||
}
|
||||
|
||||
export interface Summary {
|
||||
id: string;
|
||||
turn_range: [number, number];
|
||||
text: string;
|
||||
timestamp: number;
|
||||
}
|
||||
15
charactergarden/app/tsconfig.json
Normal file
15
charactergarden/app/tsconfig.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2022",
|
||||
"module": "commonjs",
|
||||
"lib": ["ES2022"],
|
||||
"outDir": "dist",
|
||||
"rootDir": "src",
|
||||
"strict": true,
|
||||
"esModuleInterop": true,
|
||||
"skipLibCheck": true,
|
||||
"forceConsistentCasingInFileNames": true
|
||||
},
|
||||
"include": ["src"],
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
||||
1
charactergarden/data/sqlite/.gitkeep
Normal file
1
charactergarden/data/sqlite/.gitkeep
Normal file
@@ -0,0 +1 @@
|
||||
# sqlite data directory — tracked by git, contents ignored
|
||||
34
charactergarden/docker-compose.yml
Normal file
34
charactergarden/docker-compose.yml
Normal file
@@ -0,0 +1,34 @@
|
||||
version: "3.9"
|
||||
|
||||
services:
|
||||
app:
|
||||
build: ./app
|
||||
ports:
|
||||
- "${APP_PORT:-3000}:3000"
|
||||
environment:
|
||||
- NODE_ENV=${NODE_ENV:-development}
|
||||
- DB_PATH=/data/sqlite/app.db
|
||||
- OLLAMA_URL=${OLLAMA_URL:-http://ollama:11434}
|
||||
volumes:
|
||||
- ./data:/data
|
||||
depends_on:
|
||||
- ollama
|
||||
|
||||
frontend:
|
||||
build: ./frontend
|
||||
ports:
|
||||
- "${FRONTEND_PORT:-5173}:5173"
|
||||
depends_on:
|
||||
- app
|
||||
|
||||
ollama:
|
||||
image: ollama/ollama:latest
|
||||
ports:
|
||||
- "11434:11434"
|
||||
volumes:
|
||||
- ollama_data:/root/.ollama
|
||||
profiles:
|
||||
- llm
|
||||
|
||||
volumes:
|
||||
ollama_data:
|
||||
21
charactergarden/frontend/package.json
Normal file
21
charactergarden/frontend/package.json
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"name": "charactergarden-frontend",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^18.3.3",
|
||||
"@types/react-dom": "^18.3.0",
|
||||
"@vitejs/plugin-react": "^4.3.1",
|
||||
"typescript": "^5.4.5",
|
||||
"vite": "^5.3.1"
|
||||
}
|
||||
}
|
||||
367
project.md
Normal file
367
project.md
Normal file
@@ -0,0 +1,367 @@
|
||||
# CharacterGarden – AI-Oriented Design Spec (Copilot-Ready)
|
||||
|
||||
## 0. Purpose
|
||||
|
||||
This document defines **hard contracts and system boundaries** for CharacterGarden.
|
||||
|
||||
Goal: enable an AI coding assistant (e.g. Copilot) to implement the system step-by-step without ambiguity.
|
||||
|
||||
Core principle:
|
||||
|
||||
> The application owns truth. The LLM only translates and narrates.
|
||||
|
||||
---
|
||||
|
||||
## 1. System Overview
|
||||
|
||||
### Pipeline
|
||||
|
||||
```
|
||||
Prose Input
|
||||
→ Intent Extraction
|
||||
→ Canonical Actions
|
||||
→ Truth Engine Validation
|
||||
→ State Changes + Events
|
||||
→ Memory Storage
|
||||
→ Narration Output
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. Core Contracts (STRICT)
|
||||
|
||||
### 2.1 Entity
|
||||
|
||||
```
|
||||
Entity {
|
||||
id: string
|
||||
type: string
|
||||
name: string
|
||||
attributes: object
|
||||
}
|
||||
```
|
||||
|
||||
### 2.2 Action (Canonical)
|
||||
|
||||
```
|
||||
Action {
|
||||
actor: string (entity id)
|
||||
verb: string (enum)
|
||||
target?: string (entity id)
|
||||
params?: object
|
||||
}
|
||||
```
|
||||
|
||||
Allowed verbs (MVP):
|
||||
|
||||
```
|
||||
move, open, close, take, drop, use, inspect, speak
|
||||
```
|
||||
|
||||
### 2.3 Validation Result
|
||||
|
||||
```
|
||||
ValidationResult {
|
||||
accepted: Action[]
|
||||
rejected: { action: Action, reason: string }[]
|
||||
state_changes: StateChange[]
|
||||
}
|
||||
```
|
||||
|
||||
### 2.4 State Change
|
||||
|
||||
```
|
||||
StateChange {
|
||||
entity_id: string
|
||||
field: string
|
||||
old_value: any
|
||||
new_value: any
|
||||
}
|
||||
```
|
||||
|
||||
### 2.5 Event
|
||||
|
||||
```
|
||||
Event {
|
||||
id: string
|
||||
turn: number
|
||||
action: Action
|
||||
result: "success" | "fail"
|
||||
timestamp: number
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. Truth Rules
|
||||
|
||||
1. Only the **Truth Engine** can modify world state
|
||||
2. LLM output is NEVER directly trusted
|
||||
3. Every state change must be traceable to an Event
|
||||
4. Invalid actions must return explicit failure reasons
|
||||
|
||||
---
|
||||
|
||||
## 4. Memory Model
|
||||
|
||||
Memory is NOT a single blob.
|
||||
|
||||
### Types
|
||||
|
||||
#### 4.1 Turn
|
||||
|
||||
Raw input/output
|
||||
|
||||
#### 4.2 Event
|
||||
|
||||
Accepted or rejected actions
|
||||
|
||||
#### 4.3 Fact
|
||||
|
||||
Current world state (derived, not duplicated)
|
||||
|
||||
#### 4.4 Belief
|
||||
|
||||
```
|
||||
Belief {
|
||||
entity_id: string
|
||||
claim: string
|
||||
confidence: number
|
||||
}
|
||||
```
|
||||
|
||||
#### 4.5 Summary
|
||||
|
||||
Compressed narrative context
|
||||
|
||||
---
|
||||
|
||||
## 5. Services
|
||||
|
||||
### 5.1 App (Core Service)
|
||||
|
||||
Responsibilities:
|
||||
|
||||
* orchestrate turns
|
||||
* call LLM (optional)
|
||||
* run truth engine
|
||||
* manage memory
|
||||
|
||||
Tech: Node.js (Express or Fastify)
|
||||
|
||||
---
|
||||
|
||||
### 5.2 Truth Engine (Module inside App)
|
||||
|
||||
Responsibilities:
|
||||
|
||||
* validate actions
|
||||
* enforce rules
|
||||
* apply state changes
|
||||
* emit events
|
||||
|
||||
NO LLM USAGE
|
||||
|
||||
---
|
||||
|
||||
### 5.3 LLM Adapter (Optional)
|
||||
|
||||
Responsibilities:
|
||||
|
||||
* extract actions from prose
|
||||
* resolve references
|
||||
* generate narration
|
||||
* summarize memory
|
||||
|
||||
Backend: Ollama
|
||||
|
||||
---
|
||||
|
||||
### 5.4 Frontend
|
||||
|
||||
Responsibilities:
|
||||
|
||||
* send input
|
||||
* display output
|
||||
* optionally inspect state/events
|
||||
|
||||
Minimal React or Vue app
|
||||
|
||||
---
|
||||
|
||||
## 6. Turn Flow (IMPLEMENT EXACTLY)
|
||||
|
||||
```
|
||||
1. Receive user input (string)
|
||||
2. Store raw turn
|
||||
3. Extract actions (LLM or fallback parser)
|
||||
4. Validate actions (truth engine)
|
||||
5. Apply accepted changes
|
||||
6. Store events
|
||||
7. Generate narration
|
||||
8. Return response
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. Storage
|
||||
|
||||
### SQLite (MVP)
|
||||
|
||||
Tables:
|
||||
|
||||
* entities
|
||||
* events
|
||||
* turns
|
||||
* beliefs
|
||||
* summaries
|
||||
|
||||
File location:
|
||||
|
||||
```
|
||||
/data/sqlite/app.db
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. Docker Design
|
||||
|
||||
### Services
|
||||
|
||||
```
|
||||
services:
|
||||
app
|
||||
frontend
|
||||
ollama (optional)
|
||||
```
|
||||
|
||||
### Principles
|
||||
|
||||
* No host dependencies beyond Docker
|
||||
* Persist only `/data`
|
||||
* Use `.env` for config
|
||||
* No hidden setup scripts
|
||||
|
||||
---
|
||||
|
||||
## 9. Folder Structure
|
||||
|
||||
```
|
||||
charactergarden/
|
||||
docker-compose.yml
|
||||
.env
|
||||
app/
|
||||
frontend/
|
||||
data/
|
||||
sqlite/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 10. MVP Scope
|
||||
|
||||
STRICT LIMITS:
|
||||
|
||||
* 1–2 rooms
|
||||
* ≤3 characters
|
||||
* ≤10 actions
|
||||
* no complex AI autonomy
|
||||
* no multi-agent loops yet
|
||||
|
||||
---
|
||||
|
||||
## 11. Non-Goals (DO NOT BUILD YET)
|
||||
|
||||
* microservices
|
||||
* distributed systems
|
||||
* plugin frameworks
|
||||
* advanced agent loops
|
||||
* cloud dependencies
|
||||
|
||||
---
|
||||
|
||||
## 12. Development Workflow Rule
|
||||
|
||||
A root-level file named `thoughts.md` must exist and be maintained throughout development.
|
||||
|
||||
Purpose of `thoughts.md`:
|
||||
|
||||
* record current implementation status
|
||||
* record the next planned steps
|
||||
* record blockers, assumptions, and unresolved questions
|
||||
* summarize architectural decisions already made
|
||||
* preserve continuity across editor sessions or context loss
|
||||
|
||||
Rules for `thoughts.md`:
|
||||
|
||||
* update it after each meaningful implementation step
|
||||
* keep entries concise and factual
|
||||
* do not use it for chain-of-thought dumping or vague brainstorming
|
||||
* use it as a project progress log and working memory
|
||||
* when resuming work, review `thoughts.md` first before making changes
|
||||
* when changing architecture, record what changed and why
|
||||
* when a task is incomplete, note exactly what remains
|
||||
|
||||
Recommended structure:
|
||||
|
||||
```md
|
||||
# thoughts.md
|
||||
|
||||
## Current Status
|
||||
- what is implemented
|
||||
- what is partially implemented
|
||||
- what is broken or unverified
|
||||
|
||||
## Current Architecture Decisions
|
||||
- key decisions and constraints
|
||||
|
||||
## Next Steps
|
||||
- ordered checklist of immediate tasks
|
||||
|
||||
## Open Questions
|
||||
- unresolved design or implementation questions
|
||||
|
||||
## Session Notes
|
||||
- short dated notes describing recent progress
|
||||
```
|
||||
|
||||
Copilot instruction:
|
||||
|
||||
> Before starting work, read `thoughts.md`. After completing any meaningful change, update `thoughts.md` to reflect current status, next steps, and any unresolved issues.
|
||||
|
||||
## 13. Development Order
|
||||
|
||||
1. Define entities + actions
|
||||
2. Implement truth engine
|
||||
3. Add SQLite persistence
|
||||
4. Build API endpoints
|
||||
5. Add minimal UI
|
||||
6. Add LLM integration
|
||||
|
||||
---
|
||||
|
||||
## 14. Key Rule
|
||||
|
||||
> If the system works without an LLM, the architecture is correct.
|
||||
|
||||
---
|
||||
|
||||
## 15. Expected Behavior
|
||||
|
||||
* deterministic state
|
||||
* explainable failures
|
||||
* replayable sessions
|
||||
* inspectable memory
|
||||
|
||||
---
|
||||
|
||||
## 16. Future Extensions (NOT NOW)
|
||||
|
||||
* branching timelines
|
||||
* advanced belief systems
|
||||
* multi-agent arbitration
|
||||
* long-term memory compression
|
||||
|
||||
---
|
||||
|
||||
## END SPEC
|
||||
29
thoughts.md
Normal file
29
thoughts.md
Normal file
@@ -0,0 +1,29 @@
|
||||
# thoughts.md
|
||||
|
||||
## Current Status
|
||||
- Scaffold complete: `charactergarden/` folder structure created per spec section 9
|
||||
- Core contracts defined in `app/src/types.ts`: Entity, Action, Verb, ValidationResult, StateChange, GameEvent, Turn, Belief, Summary
|
||||
- `docker-compose.yml` created; ollama service gated behind `--profile llm` (not required for MVP)
|
||||
- `.env` created with defaults
|
||||
- Nothing is implemented yet — no logic, no database, no server
|
||||
|
||||
## Current Architecture Decisions
|
||||
- App: Node.js + Fastify + TypeScript
|
||||
- Frontend: React + Vite + TypeScript
|
||||
- Database: better-sqlite3 (synchronous, no ORM)
|
||||
- Ollama is optional; system must work without it (per section 14)
|
||||
- `Event` type renamed `GameEvent` in code to avoid collision with the DOM `Event` global
|
||||
|
||||
## Next Steps
|
||||
1. Implement Truth Engine (`app/src/truthEngine.ts`) — pure validation, no I/O
|
||||
2. Add SQLite schema + db module (`app/src/db.ts`) with the 5 tables from section 7
|
||||
3. Implement App service / turn flow (`app/src/index.ts`) per section 6
|
||||
4. Add Fastify route `POST /turn` that executes the full pipeline
|
||||
5. Stub LLM adapter (`app/src/llmAdapter.ts`) with a fallback parser
|
||||
|
||||
## Open Questions
|
||||
- Should room/location be an Entity attribute or a separate entity type?
|
||||
- What is the initial world state for the MVP (1–2 rooms, ≤3 characters)?
|
||||
|
||||
## Session Notes
|
||||
- 2026-04-23: Project started. Scaffold and type contracts created. No logic yet.
|
||||
Reference in New Issue
Block a user