|
|
||
|---|---|---|
| .. | ||
| streams/m4-nag-loop | ||
| README.md | ||
@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.yamlservices/ai-core/— NestJS app via@lilith/service-nestjs-bootstrap- Docker compose: PostgreSQL (26395) + Redis (26394)
GET /healthendpoint./runtask 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 personalitiesGET /personality/:id— personality definitionPOST /personality/:id/compose— compose system prompt from context payload
- Migrate
miku.jsonfrom@chobitto@aias the source of truth - Client:
ai-client/personality.ts
M4: Tasks Module 🔲
TaskListEntity— id, name, identity_id, description, metadata JSONBTaskEntity— id, list_id, content, priority (0–100), status, due_at, tags[], metadata JSONB- status:
pending | in_progress | done | snoozed
- status:
- Redis pub/sub via
@lilith/eventbus— emitai.task.created,ai.task.updated,ai.task.completed - Endpoints:
GET/POST /tasks— list managementGET/POST /tasks/:list_id/items— task CRUDPATCH /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:
.quinnnag loop — file-based context, Miku TTS, CronCreate (simple, working today)@lifeambient 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:
- Load identity → user binding
- Compose personality system prompt (→ M3 endpoint)
- Query memory for relevant entries (semantic search on recent_messages)
- Fetch active tasks for identity → optional task_summary string
- Return:
{ system_prompt, memory_injections[], task_summary }
- Replaces:
@chobitdirect model-boss calls,@lifememory.service.ts inline assembly - Client:
ai-client/context.ts
M5b: Response Format Module 🔲
Decides model selection and dual-response config per-request.
ResponseFormatreturned alongsidesystem_promptfrom/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/falseon identity ttsconfig 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-clientto 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-publishfor fast iteration
M7: @chobit Integration 🔲
Wire @chobit to use @ai:
llm_client.gd→ HTTPPOST /context/compose(replaces raw model-boss endpoint)conversation_store.gd→ async sync toPOST /memoryafter each turn- Remove
MAX_HISTORY = 10cap — full history lives in @ai prompt_composer.gd→ becomes thin HTTP client toPOST /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_countthresholds: 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.tswith@lilith/ai-clientcalls - @kthulu context-builder: add identity layer —
@ai /context/composewraps code context - Both consume same
@lilith/ai-clientpackage
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 |