d3ro-voice/docs/map/00-index.md
Yun Chan 99f06c253c fix(llm): stop leaking instruction prompts instead of processed text
Running a custom instruction (translate, summarise, rewrite, explain code,
free prompt) inserted the instruction's own wording instead of the result.
Two faults stacked:

The instruction was passed as the text to process, leaving the system-prompt
argument empty. `BASE_SYSTEM_PROMPTS` has no `custom` key, so resolution fell
back to `refine` without saying so, and the model dutifully polished the
instruction it had been handed. The transcript never reached it.

And only `{{text}}` was substituted, which none of the five built-in
instructions use — they carry `{{targetLanguage}}`, `{{userPrompt}}`, or no
placeholder at all. The substitution was a no-op from the day it was written:
the presets landed ten hours before the code that expected them.

- Instruction prompts now go to the system-prompt argument and the transcript
  to the text argument. Instructions that spell out `{{text}}` keep their old
  meaning, so hand-written ones still work.
- `renderInstructionPrompt` resolves `{{text}}`, `{{userPrompt}}` and
  `{{targetLanguage}}` in one place, and warns by name when a placeholder is
  left standing rather than letting it reach the model.
- `resolveSystemPrompt` no longer drops silently to `refine` for `custom`.
- Voice shortcuts no longer die at the `defaultLLMAction === 'none'` gate; an
  explicitly named instruction outranks the default. Without one, `none` still
  passes the transcript through untouched.
- `translate` receives its target language instead of relying on a default two
  call frames away. It is still always English — `AppConfig` has no key for it,
  and neither `language` (UI locale) nor `sttLanguage` (source language) can
  stand in. Choosing a target language needs a setting and is not in this fix.
- Chains ran instructions with placeholders intact; they share the same
  resolution now.
- The command screen's pipeline bench called `llm.generate`, which preload does
  not expose, so every run threw and the catch showed the input back as if it
  had succeeded. It uses `llm.process` now, over the same path production
  takes, and a failure reads as a failure.

Present since the feature shipped: the custom-instruction path has never
worked. Plain actions (refine, summarise, grammar, expand) were unaffected and
are now covered by tests so they stay that way.
2026-09-21 14:39:26 +09:00

5.8 KiB
Raw Blame History

D3RO Voice — Feature & Infrastructure Map (Index)

Status: ACTIVE Last full audit: 2026-09-13 Last update: 2026-09-21 — LLM instruction-prompt fix (9c2b4d4): the custom-instruction path inserted the instruction's own wording instead of the processed result and had never worked in any shipped release (v0.1.0-alpha..v1.4.0, introduced fea923d 2026-04-05, not a regression). llm-prompts.ts is now the SSOT for prompt resolution and placeholder substitution, shared by VoiceModeService / ChainService / LLM.PROCESS. AI-04/05/06/07 are demoted to [~] on desktop — fixed with unit tests, but not verified in a running app and the four related tests/red/*.usecase.test.ts could not execute (better-sqlite3 ABI). New: GAP-LLM-01 (no target-language setting), GAP-LLM-02 (this fix unverified); GAP-INFRA-06 amended (the ABI masks verification, not just dev-env switching cost); GAP-I18N-01 amended (popup.error.default missing in 10 locales). Earlier the same day: CAP-16 (desktop key bindings rebuilt on one @d3ro/core/keybinding SSOT — multiple bindings per action, mouse buttons, HOTKEY → KEYBINDING IPC group), verified on Windows by a manual run, so CAP-16 and CAP-02 are [x] and GAP-KEY-01 is closed. Still open: GAP-KEY-02/03, GAP-QA-02, GAP-I18N-01/02, GAP-INFRA-06, GAP-LLM-01/02; 11 §7 holds accepted design constraints (things deliberately kept, not gaps) Scope: entire monorepo D:/workspace/D3ROVoice at product version 1.4.0 (release/product-version.json, released 2026-09-21) Purpose: let any agent (or human) answer two questions in under a minute:

  1. What infrastructure exists? (build, CI, services, APIs, data, packages, deploy)
  2. How far is each feature developed? (per surface, with file anchors and status)

This is the entry point. Read the index, then open only the sub-document you need. Do not read all files every time.


1. How to use this map

You need to know… Open
The product, its IA, platforms, identity/data model 01-system-overview.md
Repo layout, build, CI/CD, Docker, deploy, scripts, docs 02-infrastructure.md
Shared packages (@d3ro/core, ui, ui-native, i18n, api-client) 03-shared-packages.md
Desktop (Electron) services, IPC, pages, popups, status 04-desktop-app.md
Web (Next.js) routes, components, clients, status 05-web-app.md
Mobile (React Native) screens, features, tabs, status 06-mobile-app.md
.NET cloud API: controllers, services, tables, auth 07-api-server.md
Admin back office (Next.js) routes, guards, status 08-admin-console.md
Supabase migrations, Edge Functions, Cloudflare worker 09-supabase-backend.md
The feature map — every feature, per platform, with status 10-feature-catalog.md
Known gaps / under-developed / backlog 11-gap-backlog.md
Mandatory rules for keeping this map current 12-update-protocol.md

An agent starting a task should:

  1. Read the relevant surface doc (04–09) for infrastructure.
  2. Read 10-feature-catalog.md for the feature's current status and platform coverage.
  3. Read 11-gap-backlog.md to see if the feature is already tracked as backlog.
  4. After finishing, follow 12-update-protocol.md before the work is considered done.

2. Status legend

Feature rows in 10-feature-catalog.md use this scale:

Symbol Meaning
[x] Implemented and verified on this platform (code + tests / evidence exist in-repo).
[~] Implemented but partial, unverified, or blocked on an external/console gate.
[ ] Planned or absent on this platform.
[!] Blocked on something outside the repo (external console, secret, physical device, store review).
[-] Not applicable to this platform (with a one-line reason).

Status is per platform. A feature can be [x] on desktop, [~] on mobile, [ ] on web.


3. One-paragraph system summary

D3RO Voice is a multi-platform AI voice assistant (transcription, LLM command execution, meeting intelligence, RAG, voice conversation) sold as Free / Pro / Pro+ / Team / Enterprise tiers. It ships as an Electron desktop app (local-first: bundled SoX, faster-whisper sidecar, Ollama, local SQLite), a React Native mobile app (apps/mobile-rn, cloud-first: Supabase auth + Edge Functions + on-device Whisper fallback), a Next.js web console, a Next.js admin back office, and a .NET cloud API (AI proxy + back office backend). The shared backend is Supabase (Postgres + RLS + Auth + Storage + ~27 Deno Edge Functions), deployed to a Synology NAS via Docker with a Cloudflare edge worker and tunnel. Shared code lives in packages/*. Distribution: Windows NSIS + macOS DMG (GitLab/Forgejo feed + electron-updater), Android APK/AAB via Google Play.


4. Reading order for a brand-new agent

  1. AGENTS.md (root) — operating rules + the obligation to update this map.
  2. docs/map/01-system-overview.md — the big picture and IA.
  3. The surface doc for your task (04–09).
  4. docs/map/10-feature-catalog.md — find the feature and its status.
  5. docs/map/11-gap-backlog.md — check for existing backlog notes.

Deeper design history (not required to start): docs/design/*, docs/phases/*, docs/v2/*, docs/v3/*, memory/*, CHANGELOG.md. The mobile SSOT is docs/v3/MOBILE_APP_COMPLETION_SSOT.md.


5. Maintenance

This map must change whenever a feature is added, removed, changed, or deferred. See 12-update-protocol.md for the exact checklist and AGENTS.md for the agent obligation.