feat: add mock investigation mode for UI development

- lib/mocks/confidence-engine/mock-client.js: self-contained ESM interceptor with 6 inline turn fixtures, no external deps or require() calls
- components/scenario-form.jsx: MOCK_ENABLED compile-time boolean, useMockGlobals() hook injects window.__MOCK_* globals at runtime, ternary dispatch to mockFetch
- .env.example: NEXT_PUBLIC_CONFIDENCE_ENGINE_MOCKS, MOCK_DELAY, MOCK_SCENARIO env vars
- docs/v0.7-ui-mock-mode.md: setup, scenarios (default/complete/error), architecture, safety rules, fixture schema
This commit is contained in:
2026-08-04 13:56:15 +01:00
parent dced344680
commit 97a4847770
5 changed files with 364 additions and 4 deletions
+23 -4
View File
@@ -1,11 +1,27 @@
"use client";
import React from "react";
import { useState, useRef, useEffect, useMemo } from "react";
import React, { useEffect } from "react";
import { useState, useRef, useMemo } from "react";
import DiagnosticsView from "@/components/diagnostics-view";
import GraphUpdateView from "@/components/graph-update-view";
import SituationGraphView from "@/components/situation-graph-view";
import ReasoningWorkspace, { LoadingOverlay } from "@/components/reasoning-workspace";
import { mockFetch } from "@/lib/mocks/confidence-engine/mock-client";
/* Compile-time env resolution — NEXT_PUBLIC_ vars are injected by Next.js at build */
const MOCK_ENABLED = process.env.NEXT_PUBLIC_CONFIDENCE_ENGINE_MOCKS === "true";
/* ── inject runtime globals for the mock client to read ──── */
function useMockGlobals() {
useEffect(() => {
if (MOCK_ENABLED) {
var w = window;
w.__MOCK_ENABLED = true;
w.__MOCK_DELAY = process.env.NEXT_PUBLIC_CONFIDENCE_MOCK_DELAY || "normal";
w.__MOCK_SCENARIO = process.env.NEXT_PUBLIC_CONFIDENCE_ENGINE_MOCK_SCENARIO || "";
}
}, []);
}
const MAX_LENGTH = 10000;
@@ -191,6 +207,9 @@ export default function ScenarioForm() {
const [lastSubmittedAnswer, setLastSubmittedAnswer] = useState("");
const textareaRef = useRef(null);
/* Inject mock globals so the interceptor can read them at runtime */
useMockGlobals();
const { elapsed: startElapsed, currentMessage: startMsg } = useLoadingStatus(
INITIAL_MESSAGES,
status === "loading"
@@ -214,7 +233,7 @@ export default function ScenarioForm() {
setUpdateResult(null);
try {
const res = await submitScenarioForStartCase(fetch, scenario);
const res = await submitScenarioForStartCase(MOCK_ENABLED ? mockFetch : fetch, scenario);
const data = await res.json();
@@ -245,7 +264,7 @@ export default function ScenarioForm() {
setUpdateError(null);
setLastSubmittedAnswer(answer.trim());
const submission = await submitAnswerForUpdateCase(fetch, {
const submission = await submitAnswerForUpdateCase(MOCK_ENABLED ? mockFetch : fetch, {
situationGraph: result?.situationGraph,
previousQuestion: result?.selectedQuestion,
answer,