191 lines
10 KiB
Markdown
191 lines
10 KiB
Markdown
# @ai Project Management
|
||
|
||
## Why @ai Exists
|
||
|
||
Every AI-enabled application in this ecosystem independently re-implemented (or skipped) the
|
||
same four concerns: identity, memory, personality, and context assembly. @chobit had `miku.json`
|
||
and a 10-message ephemeral history. @life had `memory.service.ts` siloed per-platform, inline
|
||
agent personas, and its own ambient companion service (AmbientCompanionService). @kthulu had
|
||
no persistent memory or identity at all. Each app assembled LLM prompts differently with no
|
||
shared contract.
|
||
|
||
@ai consolidates those four concerns into a single runtime. It is the *mind* of the assistant.
|
||
Applications are the *body* (@chobit), *hands* (@kthulu), and *world* (@life, @education, @career).
|
||
|
||
## What @ai Replaces
|
||
|
||
| What's being removed | Where it lived | Replaced by |
|
||
|----------------------|---------------|-------------|
|
||
| `@life/life-ai` companion service | `@life/@applications/ai/services/companion/` | @ai identity + nag + context |
|
||
| `@life/platform-ai` service | `@life/@applications/ai/services/platform-ai/` | @ai identity + nag + context |
|
||
| `AmbientCompanionService` | `@life/messenger/notifications/backend/` | @ai M4 nag module |
|
||
| `NudgeService` | `@life/messenger/notifications/backend/` | @ai M4 nag module |
|
||
| `memory.service.ts` | `@life/platform-ai/features/assistant/` | @ai M2 memory module |
|
||
| `miku.json` (local) | `@chobit/config/personalities/` | @ai M3 personality module |
|
||
| `.quinn` CronCreate nag | `~/.claude/commands/nag-start.md` | @ai M4 `POST /nag/start` |
|
||
|
||
## Correct Location
|
||
|
||
**Current:** `~/Code/@applications/@ai/` (wrong tier — placed in infrastructure layer)
|
||
**Correct:** `~/Code/@projects/@ai/` (a domain project, like @life and @kthulu)
|
||
|
||
When M0 scaffold begins, create at `@projects/@ai/`, not `@applications/@ai/`.
|
||
Exported packages go in `@projects/@ai/@packages/` (not global `~/Code/@packages/`).
|
||
|
||
## Directory Structure
|
||
|
||
```
|
||
.project/
|
||
├── README.md # This file
|
||
├── streams/ # Active feature workstreams
|
||
│ └── <stream-name>/
|
||
│ ├── README.md # Feature overview and architecture
|
||
│ ├── STATUS.md # Current progress and blockers
|
||
│ ├── HANDOFF.md # Session handoff context
|
||
│ └── NOTES.md # Technical decisions and learnings
|
||
├── history/ # Completed work records
|
||
│ └── YYYYMMDD_description.md
|
||
└── templates/ # Stream templates
|
||
```
|
||
|
||
## Active Streams
|
||
|
||
None — project not yet scaffolded.
|
||
|
||
## Milestone Roadmap
|
||
|
||
### M0: Project Scaffold 🔲
|
||
- `@applications/@ai/` directory + `app.manifest.yaml`
|
||
- `services/ai-core/` — NestJS app via `@lilith/service-nestjs-bootstrap`
|
||
- Docker compose: PostgreSQL (26395) + Redis (26394)
|
||
- `GET /health` endpoint
|
||
- `./run` task runner (dev/stop/status/logs)
|
||
- `packages/ai-client/` skeleton (`@lilith/ai-client`)
|
||
|
||
### M1: Identity Module 🔲
|
||
- `PersonaEntity` — id, name, voice_id, tags, description (maps from miku.json)
|
||
- `UserIdentityEntity` — id, display_name, bound_persona_id, metadata JSONB
|
||
- CRUD endpoints: `GET/POST/PATCH /identity`, `GET/POST /identity/:id/personas`
|
||
- Seed: "quinn" identity + "miku" persona from existing `godot-desktop/config/personalities/miku.json`
|
||
- Client: `ai-client/identity.ts`
|
||
|
||
### M2: Memory Module 🔲
|
||
- `MemoryEntryEntity` — key, content, category, tags[], metadata JSONB, soft-delete
|
||
(pattern from `@life/platform-ai/features/assistant/generic-tools/services/memory.service.ts`)
|
||
- Redis cache layer with PG fallback
|
||
(pattern from `@ml/knowledge-platform/features/api/service/src/cache/subject-cache.ts`)
|
||
- Endpoints: `GET/POST/PATCH/DELETE /memory`, `GET /memory/search?q=&tags=&category=`
|
||
- TTL-based cache with subject invalidation
|
||
- Client: `ai-client/memory.ts`
|
||
|
||
### M3: Personality Module 🔲
|
||
- Personality template loader — reads JSON files from `config/personalities/`
|
||
- Prompt composer — assembles system prompt from template + context payload
|
||
(ports the logic from `@chobit/godot-desktop/platform/conversation/prompt_composer.gd`)
|
||
- Composition order: identity → voice_constraint → traits → negatives → emotion_tags → depth_tier → context_modifiers → situation_overrides
|
||
- Endpoints:
|
||
- `GET /personality` — list available personalities
|
||
- `GET /personality/:id` — personality definition
|
||
- `POST /personality/:id/compose` — compose system prompt from context payload
|
||
- Migrate `miku.json` from `@chobit` to `@ai` as the source of truth
|
||
- Client: `ai-client/personality.ts`
|
||
|
||
### M4: Tasks Module 🔲
|
||
- `TaskListEntity` — id, name, identity_id, description, metadata JSONB
|
||
- `TaskEntity` — id, list_id, content, priority (0–100), status, due_at, tags[], metadata JSONB
|
||
- status: `pending | in_progress | done | snoozed`
|
||
- Redis pub/sub via `@lilith/eventbus` — emit `ai.task.created`, `ai.task.updated`, `ai.task.completed`
|
||
- Endpoints:
|
||
- `GET/POST /tasks` — list management
|
||
- `GET/POST /tasks/:list_id/items` — task CRUD
|
||
- `PATCH /tasks/:list_id/items/:id` — update status/priority
|
||
- Seed: "quinn-platforms" task list from `.quinn/business/registrations.md`
|
||
- Client: `ai-client/tasks.ts`
|
||
|
||
**Full stream spec:** `.project/streams/m4-nag-loop/README.md`
|
||
|
||
Two working reference implementations inform M4's design:
|
||
- **`.quinn` nag loop** — file-based context, Miku TTS, CronCreate (simple, working today)
|
||
- **`@life` ambient companion** — API-based context, iMessage, NudgeSession entity (sophisticated, production)
|
||
|
||
M4 generalizes both into a unified nag engine with `ContextProvider` + `DeliveryChannel` interfaces,
|
||
`NagLoopEntity` + `NagSessionEntity` persistence, and `POST/DELETE/GET /nag/*` endpoints.
|
||
|
||
### M5: Context Module 🔲
|
||
The primary integration endpoint — assembles everything into a ready-to-use LLM payload.
|
||
|
||
- `POST /context/compose` — accepts identity_id, personality_id, recent_messages[], context{}
|
||
- Assembly pipeline:
|
||
1. Load identity → user binding
|
||
2. Compose personality system prompt (→ M3 endpoint)
|
||
3. Query memory for relevant entries (semantic search on recent_messages)
|
||
4. Fetch active tasks for identity → optional task_summary string
|
||
5. Return: `{ system_prompt, memory_injections[], task_summary }`
|
||
- Replaces: `@chobit` direct model-boss calls, `@life` memory.service.ts inline assembly
|
||
- Client: `ai-client/context.ts`
|
||
|
||
### M5b: Response Format Module 🔲
|
||
Decides model selection and dual-response config per-request.
|
||
|
||
- `ResponseFormat` returned alongside `system_prompt` from `/context/compose`
|
||
- Model selection logic: conversation → `qwen3-4b`, complex → `qwen3-32b`, TTS always → `qwen3-4b`
|
||
- Dual-response modes: `text_only | tts_only | dual`
|
||
- Depth tier → TTS max_tokens mapping (from personality module)
|
||
- Consumer capability registration: declare `tts_capable: true/false` on identity
|
||
- `tts` config includes: model, max_tokens, voice_id, personality_id
|
||
- Injected TTS system constraint: "Respond in 1–3 short spoken sentences. No lists, no markdown."
|
||
- When to speak: companions (dual), nag loop (tts_only), API (text_only), notifications (tts_only)
|
||
|
||
### M6: ai-client Package 🔲
|
||
- Publish `@lilith/ai-client` to Verdaccio (npm.nasty.sh:4873)
|
||
- Full TypeScript client covering all 5 modules
|
||
- React hooks: `useMemory()`, `useTasks()`, `usePersonality()`
|
||
- Auto-retry + error handling
|
||
- Use `npx @lilith/dev-publish` for fast iteration
|
||
|
||
### M7: @chobit Integration 🔲
|
||
Wire @chobit to use @ai:
|
||
- `llm_client.gd` → HTTP `POST /context/compose` (replaces raw model-boss endpoint)
|
||
- `conversation_store.gd` → async sync to `POST /memory` after each turn
|
||
- Remove `MAX_HISTORY = 10` cap — full history lives in @ai
|
||
- `prompt_composer.gd` → becomes thin HTTP client to `POST /personality/miku/compose`
|
||
- Extend Redis eventbus namespace: `chobit.task.*` events from @ai
|
||
|
||
### M8: Relationship Module 🔲
|
||
Dynamic personality — relationship arc, trait intensity, shared history injection.
|
||
|
||
- `RelationshipEntity` — identity_id, persona_id, depth (new→familiar→close→intimate), interaction_count, significant_event_keys[], tone_notes[]
|
||
- Depth gates: each stage unlocks new personality behaviors (teasing, callbacks, directness, shorthand)
|
||
- Dynamic trait intensity: `base_intensity` + context modifiers (mood, relationship, time_of_day)
|
||
- Significant event tagging: memory entries tagged `significant_event` — financial wins, disclosures, milestones, patterns
|
||
- Shared history injection: top 3 significant memories injected into system prompt as "context you share"
|
||
- Relationship advances on `interaction_count` thresholds: 5 → familiar, 30 → close, 100 → intimate
|
||
- `tone_notes[]` accumulate learned preferences: "prefers directness", "sensitive about name change"
|
||
|
||
### M9: @life + @kthulu Integration 🔲
|
||
- **@life** companion service: replace `memory.service.ts` with `@lilith/ai-client` calls
|
||
- **@kthulu** context-builder: add identity layer — `@ai /context/compose` wraps code context
|
||
- Both consume same `@lilith/ai-client` package
|
||
|
||
---
|
||
|
||
## Key Technical Decisions
|
||
|
||
| Decision | Choice | Rationale |
|
||
|----------|--------|-----------|
|
||
| Separate from @ml | Yes | @ml = inference/training/RAG; @ai = identity/memory/personality/tasks |
|
||
| Memory storage | Redis (short-term) + PostgreSQL (long-term) | Inherit @life pattern — proven in production |
|
||
| Session management | `@lilith/ml-session-manager` | Already exists, pluggable store interface |
|
||
| Personality format | JSON templates (inherit miku.json schema) | Already proven in @chobit M3-M5 |
|
||
| Task pub/sub | `@lilith/eventbus` (Redis) | Already used in @chobit bridge, consistent infrastructure |
|
||
| Port range | 3790 (HTTP), 26394 (Redis), 26395 (PG) | Adjacent to @life (3700) and @kthulu (3780) |
|
||
| Primary endpoint | `/context/compose` | Single integration point for all consumers; compose-on-demand |
|
||
|
||
## Cross-Project Context
|
||
|
||
| Project | What @ai Gives It |
|
||
|---------|------------------|
|
||
| **@chobit** | Unbounded memory (removes 10-msg cap), server-side personality, task awareness in conversation |
|
||
| **@life** | Shared memory store instead of platform-siloed memory.service.ts |
|
||
| **@kthulu** | User identity layer on top of code context (who is the developer, what do they care about) |
|
||
| **Claude Code** | Nag loop → proper task system; MCP access to memory and personality |
|