357 Commits

Author SHA1 Message Date
Codex Local 1be38a9f21 feat(chat): thinking panel + relay fix
Backend:
- Add WS event "thinking" (start/stream/done) with
  throttled 150ms streaming, replacing system messages
- Fix inter-persona relay: [RELAI INTER-PERSONA] block
  + [PROTOCOLE CANAL 3615] directive prevents personas
  from rejecting relay as injection
- Fix resolveRuntimeModel fallback to LLM_MODEL
- Switch from mascarade to direct local vLLM streaming
- Fix llmHeaders: read API key at call time (ESM order)
- Add shouldThink: disable qwen3 thinking for short msgs
  via chat_template_kwargs.enable_thinking
- Increase THINKING_HEADROOM to 2048
- Remove double-strip: onDone passes raw text, caller
  strips via cleanPersonaResponse
- stripThinking handles unclosed <think> tags

Frontend:
- ThinkingPanel: collapsible right drawer with live
  thinking stream per persona + progress bar
- useChatState: thinkingByPersona state + WS handler
- styles.css: panel styles, responsive hide <800px
- Fix TimelineView meta type error (pre-existing)
2026-04-13 17:19:09 +02:00
Codex Local 1930f03b7f refactor: deduplicate extractFirstJsonObject
Extract shared extractFirstJsonObject() into json-utils.ts and
replace the 4 identical copies in composition-store, context-store,
ws-chat, and media-store with imports.
2026-04-12 16:07:30 +02:00
Codex Local a2271a807e refactor: remove dead code
Remove unused SENTENCE_END regex and extractSentences() from
ws-conversation-router.ts (TTS sentence splitting, no longer called)
and shouldThink() from ws-ollama.ts (adaptive thinking, never called).
2026-04-12 16:07:23 +02:00
Codex Local c84c3d8e07 chore: add corpus ingestion and persona tooling
Offline scripts for maintaining the persona and RAG subsystems.

- ingest_spectacle_corpus.py: bulk-load texts into LightRAG
- camoufox_server.py: headless browser proxy for scraping
- audit_personas.py: validate persona configs against store
- generate-persona-dialogues.js: synthetic dialogue generator
2026-04-12 15:50:22 +02:00
Codex Local c809beab8e feat: thinking progress UX with persona flavour
Show real-time thinking/reasoning progress in the chat UI with
persona-specific flavour texts for a more engaging experience.

- Extend ws-conversation-router with thinking state machine
- Stream thinking tokens to frontend via useChatState hook
- Add persona flavour text display in Chat component
- Simplify ws-commands-info and ws-commands-compose routing
- Update ComposePage with server status panel
- Add integration and router tests for thinking flow
2026-04-12 15:49:56 +02:00
Codex Local ea6a129ee3 feat: migrate LLM backend to llama-server
Switch from Ollama API format to OpenAI-compatible llama-server
with reasoning token support.

- Refactor ws-ollama to emit OpenAI chat completions format
- Update llm-client endpoint configuration
- Add reasoning/thinking token extraction to web-search
- Update smoke tests for new response shape
- Add llama-server deployment to k8s manifests
- Update README with new architecture notes
2026-04-12 15:49:34 +02:00
Codex Local 1f86e4734e fix: JSON corruption recovery with atomic writes
Prevent data loss from truncated JSON files caused by crashes or
concurrent writes.

- Add extractFirstJsonObject helper for recovering partial JSON
- Switch composition-store and media-store to atomic writes (tmp+rename)
- Harden chat-history and media routes with graceful error handling
- Improve ws-chat resilience against malformed stored state
- Add tests for corruption recovery and atomic save paths
2026-04-12 15:49:17 +02:00
Codex Local 7a2e81ae5a feat: nick-isolated persona memory system
Persona memories are now scoped per-nick, preventing cross-user
contamination in shared channels.

- Add auto/explicit memory modes to persona-memory-store
- Extend chat-types with memory-related message fields
- Refactor ws-commands-chat to route through memory layer
- Expand personas-default with richer persona definitions
- Update persona-memory-policy for mode selection
- Add tests for nick-scoped storage and retrieval
2026-04-12 15:48:58 +02:00
Codex Local 14991c50f8 fix: use findLastChunkIndex for chunk accumulation
Chunk messages from the same persona were displayed as separate lines
instead of being concatenated into a single streaming message. The root
cause: audio (TTS) and system (typing indicator) messages interleaved
between chunks, and the accumulator only checked the very last array
element. Now uses findLastChunkIndex to search backward through the
full message array, matching the logic already used for final message
replacement.
2026-04-12 01:20:30 +02:00
Codex Local 9c0487f05e fix: route chat to vLLM, not embedding server
ollamaUrl in WS chat and ContextStore now uses
LLM_URL instead of embedding URL.
2026-04-08 14:10:54 +02:00
Codex Local b306eff8d5 fix: Docker API env vars for vLLM/TEI
- Copy packages dist/ in Dockerfile
- Fix env vars in api service (vLLM :8000, TEI :8001)
- Remove duplicate RAG_EMBEDDING_MODEL key
2026-04-08 10:52:18 +02:00
Codex Local 0b8da7b1e8 fix: use existing embed-server on :8001
Remove duplicate TEI service, point to existing
nomic-embed-text-v1.5 server.
2026-04-08 10:02:30 +02:00
Codex Local 3c20f94908 feat: add dotenv for auto .env loading
No more manual env var export needed.
2026-04-08 09:45:57 +02:00
Codex Local c5f921243e feat: wire vLLM + TEI embedding backend
- LLM_API_KEY support across all LLM calls
- TEI embedding server (bge-m3, :9500)
- Hierarchical AGENTS.md documentation
- CLAUDE.md updated for new architecture
2026-04-08 09:41:51 +02:00
Codex Local 2beaaf6179 fix: atomic composition saves + deep audit P0/P1 fixes
Deep audit 2026-03-26 (10 findings, 4 fixes):
- FINDING-1 P0: saveComposition async + atomic write (tmp+rename) — prevents partial JSON on concurrent saves
- FINDING-2 P0: MAX_COMPOSITIONS (500), MAX_COMPOSITION_BYTES (512KB), MAX_TRACKS_PER_COMPOSITION (100) env-configurable
- FINDING-3 P1: ttsQueues self-cleans via .finally() after chain drains
- FINDING-4 P1: personaMemoryLocks reset to Promise.resolve() in .finally() — prevents unbounded chain growth
- lot-204: docs/LOT204_TRAINING_SPIKE.md (OpenCharacter + PCL, GO verdict, 4 sub-lots, RTX 4090 sufficient)
- lot-30: docs/LOT030_TTS_EVALUATION.md (Pocket TTS: watch — EN-only blocker, FR planned, no date)
- docs/DEEP_AUDIT_2026-03-26.md: 10 findings P0-P2 catalogued

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-26 11:43:26 +01:00
Codex Local 854fd7f932 feat: memory benchmark, ComposePage server panel, RAG/journald ops
- lot-203: LOT203_MEMORY_BENCHMARK.md — Mem0 vs local store (verdict: keep local; 300-2000ms vs <5ms, 3 extra services vs 0)
- ComposePage: "☁ Serveur" button + panel listing server-side compositions from /api/v2/media/compositions
- lot-28-rag-config: confirmed done (RAG_CHUNK_SIZE/MIN_SIMILARITY/MAX_RESULTS/EMBEDDING_MODEL in rag.ts)
- lot-29-systemd: scripts/journald-monitor.sh (TUI status, --watch mode, CI exit code) + ops/v2/journald-alerts.conf
- scripts/cleanup-test-compositions.js: dry-run cleanup tool for stale test compositions on disk
- PLAN.md lot-28 [planned] → [done]

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-26 11:31:11 +01:00
Codex Local 004ea2907d feat: timeline UI v1 + composition tests + legacy cleanup
- lot-547: TimelineModelV1 schema confirmed (Track, TimelineClip, TimelineMarker, bpm, timeSignature)
- lot-548: TimelineView.tsx (RAF playback, ruler seek, clip blocks, marker legend, mobile CSS), lazy-routed at #timeline/:id
- lot-549: composition-store.test.ts 20 tests (setActiveComposition, BPM clamp [20-300], timeSignature clamp >=1, marker sort, multi-track clips, gain clamp [0-200])
- lot-205: remove legacy personas.json / persona-*.json fallback from create-repos.ts (migration window closed, no legacy files on disk)
- lot-206: confirmed no createInMemory* aliases remaining
- P11: all four route extractions confirmed (routes/personas.ts, routes/node-engine.ts, routes/chat-history.ts, app-middleware.ts)
- Fix /delete ws-commands.test: RUN_ID suffix prevents nick/channel collision with disk-persisted compositions (85 stale compositions found on startup)
- 278 tests, 0 fail

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-26 11:19:32 +01:00
Codex Local d249777d84 feat: add persona memory telemetry + session cleanup
- Instrument ws-persona-router with attempt/write/skip/failure recording
- Expose persona_memory stats in GET /api/v2/perf endpoint
- Export Prometheus series for persona memory in /metrics
- Add app.test.ts cases for perf and Prometheus persona memory endpoints
- Clean up obsolete composition and ws-commands test stubs
- Update AGENTS.md/PLAN.md/TODO.md: session 2026-03-25 personas V2 runtime hardening
- Remove DAW e2e test skip
2026-03-26 10:15:38 +01:00
Codex Local 267ae228be feat(personas): add configurable memory policy engine 2026-03-26 08:20:00 +01:00
Codex Local 2fcac5ff1c chore(personas): align memory cleanup and specs 2026-03-25 22:34:00 +01:00
Codex Local 35bd94a4b5 feat(personas): migrate runtime memory to v2-local store 2026-03-25 22:34:00 +01:00
Codex Local 085eb06d49 docs(personas): define v2 memory schema baseline 2026-03-25 22:34:00 +01:00
Codex Local 9ac151a59d docs(ops): add persona store audit and lot tracking 2026-03-25 22:34:00 +01:00
Codex Local d4188583ab fix(personas): converge feedback runtime and dpo export 2026-03-25 22:34:00 +01:00
Codex Local c461f4e6ca fix(personas): make local migration loaders retryable 2026-03-25 22:34:00 +01:00
Codex Local 25ad84fc69 fix(personas): merge partial legacy stores into per-file runtime 2026-03-25 22:34:00 +01:00
Codex Local 9d687dda5e docs(ops): track lot-204 persona memory benchmark and harden log purge 2026-03-25 22:34:00 +01:00
Codex Local 65d4cad55a refactor(runtime): harden local repo snapshots and drop legacy local aliases 2026-03-25 22:34:00 +01:00
Codex Local 88e14f9b16 refactor(personas): expose local storage mode and canonical local repos 2026-03-25 22:34:00 +01:00
Codex Local e1d1f083af chore(smoke): remove legacy persona dir snapshots from v2 flow 2026-03-25 22:34:00 +01:00
Codex Local ccb9e93e1c chore(build): gate legacy persona dirs behind compat flag 2026-03-25 22:34:00 +01:00
Codex Local 1c08799766 chore(smoke): drop legacy personas.overrides snapshot in v2 flow 2026-03-25 22:34:00 +01:00
Codex Local c345616603 chore(build): gate legacy persona overrides behind explicit compat flag 2026-03-25 22:34:00 +01:00
Codex Local 62486d0d6e docs(personas): document v2-local per-file store and legacy-only paths 2026-03-25 22:34:00 +01:00
Codex Local 7807a6c5b8 chore(personas): align smoke/build scripts with v2-local per-file store 2026-03-25 22:34:00 +01:00
Codex Local d23eba6d42 test(personas): cover legacy per-file migration and defensive repo snapshots 2026-03-25 22:34:00 +01:00
Codex Local 0bc692f048 chore(personas): add migration scripts for per-file local store 2026-03-25 22:34:00 +01:00
Codex Local e06c5b4e87 personas: migrate local store to per-file runtime and harden repo reads 2026-03-25 22:34:00 +01:00
L'électron rare 76bac17334 Refactor code structure for improved readability and maintainability 2026-03-24 19:14:56 +01:00
L'électron rare 1b7bd46b41 qa: visual-qa 36 tests + fix /theme dark|light + fkey scroll 320px
- feat: apps/web/e2e/visual-qa.spec.ts — 36 tests E2E design (36 passed)
  - 9 describe: connexion, chat, themes, navigation, responsive, a11y, composants, contraste, typo
  - 30 screenshots dans apps/test-results/visual-qa/
  - viewports: 320/375/768/1280/1920px
  - thèmes: noir/matrix/amber/ocean/dark/light
  - pages: chat, compose, imagine, daw, gallery, voice
- fix: ws-commands-info.ts — ajout 'dark' et 'light' aux thèmes autorisés
  - avant: ['minitel','noir','matrix','amber','ocean']
  - après: + dark, light
- fix: styles.css — barre fkey scrollable sur ≤340px (flex-wrap:nowrap, overflow-x:auto)
- docs: QA_WEBDESIGN_2026-03-24.md — rapport complet QA design
2026-03-24 18:35:57 +01:00
L'électron rare 4027c33a38 test: fix E2E Playwright pour prod 3115.kxkm.net — 25 passed 9 skipped 0 failed
- app.spec.ts: suppression assertions local-only (Backend Playwright, Reponse deterministe)
  correcteur selecteur .chat-channel → .chat-channel-btn, skip admin test (credentials CI)
- commands.spec.ts: compteur /help 103→112, weather °C (case-insensitive), nav .minitel-fkey
- daw.spec.ts: selector DAW AI (bouton label fix), check openDIAW.be conditionnel
- daw-instruments-debug.spec.ts: skip global (service interne kxkm-ai:3333 non accessible CI)
- instruments.spec.ts: skip sound-design (generation IA >20s, tester manuellement)
- playwright.config.ts: baseURL TEST_BASE_URL=https://3115.kxkm.net, workers=1, retries=1
2026-03-24 18:16:39 +01:00
L'électron rare 6e13c26954 refactor: lot-192 phase 3 — extract ws-commands-compose advanced handlers (/concat /silence /template /marker /metronome /delete /suggest /snapshot /randomize)
- Add COMPOSE_ADVANCED_COMMANDS set + createComposeAdvancedCommandHandler to ws-commands-compose.ts
- Route all 9 advanced composition cmds before generate switch in ws-commands-generate.ts
- -695 LOC in ws-commands-generate.ts
- Add /delete + /marker regression tests in ws-commands.test.ts
- Sync PLAN.md, TODO.md, AGENTS.md, docs/AGENTS.md
2026-03-24 18:00:23 +01:00
L'électron rare f015455b20 chore: align local snapshot for kxkm-ai sync 2026-03-24 17:14:02 +01:00
L'électron rare afe70ba7a4 docs: update PLAN + TODO — lots 534-544 done, sprint P0/P1 complete
Session 2026-03-24: 11 lots (534-544)
- /deepresearch multi-step agent, mascarade thinking fix
- Grafana 16 panels, Cloudflare Tunnels (7 hostnames)
- Regex intent fix + 13 tests, async ffmpeg, worker unification, Chat memo

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 15:52:13 +01:00
L'électron rare aca7894746 perf: lot 544 — Chat render memoization (wordCount + searchMatches)
- useMemo for wordCount (was inline .reduce on every render across 500+ msgs)
- useMemo for searchMatches (was creating new Set on every render)
- Both now only recompute when messages/searchQuery actually change

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 15:51:32 +01:00
L'électron rare 93533ca14f refactor: lot 543 — worker index.ts unified on worker-runtime.ts
- index.ts reduced from 583 LOC to 155 LOC (thin orchestrator)
- All logic delegated to worker-runtime.ts exports:
  createShutdownController, createNodeExecutor, runPollCycle, waitForNextPollTick
- Removed duplicated executeRun, executeNodeStub, syncQueuedRuns, etc.
- Single source of truth for poll/dequeue/execute cycle
- 6/6 worker-runtime tests pass

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 15:50:04 +01:00
L'électron rare 3a68887712 perf: lot 542 — async ffmpeg (unblock event loop during mix/export)
- Replace all execFileSync("ffmpeg") with await execFileAsync("ffmpeg")
  across ws-commands-generate.ts (~35 calls)
- Remove stale execFileSync dynamic imports (2 occurrences)
- Remove unused execFileSync import from ws-commands-info.ts
- Event loop stays free during /mix, /master, /bounce, /fx, /noise, etc.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 15:48:45 +01:00
L'électron rare 45ef9864b1 fix: lot 541 — regex intent extraction fix + 13 non-regression tests
- Fix: "\s*" in string literal was "s*" not whitespace — changed to "\\s*"
- Extract detectGenerationIntent as exported standalone function (testable)
- 13 new tests: FR image (4), EN image (2), FR music (3), EN music (1), negative (3)
- All 21 conversation-router tests pass

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 15:47:16 +01:00
L'électron rare 726cccb155 feat: lot 537 — Cloudflare Tunnels (kxkm-ai + tower, 7 public hostnames)
2 tunnels deployed via Cloudflare API:
- kxkm-ai-gpu: kxkm.saillant.cc (:3333), kxkm-api (:3333),
  kxkm-mascarade (:8100), kxkm-comfy (:8188)
- intello-cockpit (tower): kxkm-tower (:3334), kxkm-grafana (:3001),
  mascarade (:8100 + Authentik SSO)

Replaces planned lots 538-540 (firewall/Tailscale/nginx/certbot).
HTTPS auto, no ports to open, no firewall rules needed.
Anthropic domain verification TXT record added to saillant.cc.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 15:43:35 +01:00
L'électron rare c9faf9f8fb feat: lot 536 — Grafana dashboard enriched + Prometheus multi-machine + metrics
Dashboard (16 panels):
- Top row: WS connections, chat/min, LLM calls, tokens, RSS, uptime
- Latency: HTTP p50/95/99, Ollama TTFB+total, persona response, RAG search+rerank
- WS message latency, memory heap/RSS timeseries
- Errors by label (stacked bars), request throughput (chat/commands/LLM/TTS/image)
- Service counters table (all cumulative metrics)

Prometheus: multi-machine scrape (kxkm-ai:3333, tower:3334, mascarade:8100)
Metrics: deep_research counter + latency recording

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 12:50:23 +01:00