de333852e7
Mirrors step 3.5 self-assessment pattern (c1ec61fa). When embedding-mode=on and task is non-trivial (per shouldEmbed), computes Xenova 384-dim embedding via Promise.race with 2s timeout. Result -> prompt_embedding_base64 base64 string, or null + environment.embedding_unavailable=true on timeout/failure. Closes Phase 4 follow-up "embedding async wiring" (was deferred from Phase 3 deferred #2 / parser write-block — parser writes the slot, CLI now fills it). Extracted core into exported helper computeEmbeddingForEpisode(ep, ctx, opts) with injectable embedFn / shouldEmbedFn / encodeBase64Fn / timeoutMs, mirroring the pure-API style of callSelfAssessmentApi. CLI binds the real router-embedding.mjs implementations; tests inject fakes. 4 new tests: - embedding-mode off -> field null - taskType=conversation (exempt) -> embedding skipped - embedding success -> base64 string - embedding timeout -> environment.embedding_unavailable=true Regression: 650/650 tests passed (35 test files), 0 failed (excluding 4 pre-existing empty ruflo-*/subagent-prompt-prefix test files).