ai/.project
autocommit 21fb00766c chore(config): 🔧 Update IDE/build configuration settings in project config file
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
2026-04-12 19:06:54 -07:00
..
streams/m4-nag-loop chore(config): 🔧 Update IDE/build configuration settings in project config file 2026-04-12 19:06:54 -07:00
README.md chore(config): 🔧 Update IDE/build configuration settings in project config file 2026-04-12 19:06:54 -07:00

@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 (0100), 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 13 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