chore: establish clean v0.2 baseline

Include only the working reconstruction prototype with Ollama integration:
- double-wrapping fix (lib/llm/provider.js)
- explicit v0.2 JSON output schema (prompts/reconstruct-v0.2.md)
- Zod validation layer (lib/reconstruction/schema.js)
- shared core analysis path (lib/analysis.js)
- prompt versioning infrastructure (lib/reconstruction/prompt.js)
- provider abstraction
- functioning Ollama provider path
- updated API route with centralized analysis
- UI components displaying v0.2 data and validation errors
- .gitignore rules for generated evaluation artifacts

Exclude: evaluator experiments, diagnostic tests, debug scripts,
generated artifacts, comparison findings, test data tied to evaluator.
This commit is contained in:
2026-08-01 14:45:06 +01:00
parent a2f9e472ea
commit d72c7c5465
11 changed files with 1048 additions and 172 deletions
+50 -22
View File
@@ -8,7 +8,7 @@ const MAX_LENGTH = 10000;
export default function ScenarioForm() {
const [scenario, setScenario] = useState("");
const [status, setStatus] = useState("idle"); // idle | loading | error | success
const [status, setStatus] = useState("idle"); // idle | loading | error | success | partial
const [result, setResult] = useState(null);
const textareaRef = useRef(null);
@@ -29,6 +29,10 @@ export default function ScenarioForm() {
if (res.ok && data.validationStatus === "valid") {
setStatus("success");
setResult(data);
} else if (data.success) {
// Success in analysis but validation may be partial
setStatus("success");
setResult(data);
} else {
setStatus("error");
setResult(data);
@@ -39,8 +43,13 @@ export default function ScenarioForm() {
}
};
// Always show diagnostics when there's a result (even if validation failed)
const hasDiagnostics = result && (result.reconstruction || result.modelName || result.responseDurationMs !== undefined);
// Determine if we have meaningful content to display
const hasClassification = result?.inputClassification;
const hasReconstruction = result?.reconstruction;
const hasNextQuestion = result?.nextQuestion;
const hasEvidence = result?.evidence && result.evidence.length > 0;
const hasMeaningfulContent =
hasClassification || hasReconstruction || hasNextQuestion || hasEvidence;
return (
<div className="space-y-6">
@@ -54,7 +63,9 @@ export default function ScenarioForm() {
className="w-full rounded-lg border border-gray-300 px-4 py-3 text-sm focus:border-gray-500 focus:outline-none focus:ring-2 focus:ring-gray-400"
/>
<div className="flex items-center justify-between">
<span className="text-xs text-gray-400">{scenario.length}/{MAX_LENGTH}</span>
<span className="text-xs text-gray-400">
{scenario.length}/{MAX_LENGTH}
</span>
<button
type="submit"
disabled={status === "loading" || !scenario.trim()}
@@ -65,6 +76,7 @@ export default function ScenarioForm() {
</div>
</form>
{/* Error state */}
{status === "error" && (
<div className="space-y-3">
{result?.error && (
@@ -72,35 +84,51 @@ export default function ScenarioForm() {
Error: {result.error}
</div>
)}
{hasDiagnostics && result?.modelName && (
<dl className="grid grid-cols-[auto_1fr] gap-x-4 gap-y-1.5 text-sm">
<dt className="text-gray-500">Model</dt>
<dd>{result.modelName}</dd>
<dt className="text-gray-500">Duration</dt>
<dd>{result.responseDurationMs != null ? `${result.responseDurationMs}ms` : "?"}</dd>
</dl>
{/* Show partial content even on validation failure */}
{(hasClassification || hasReconstruction) && (
<div className="rounded-lg border border-yellow-300 bg-yellow-50 px-4 py-2 text-sm text-yellow-800">
Partial result some fields failed validation. Showing what was
accepted.
</div>
)}
{hasReconstruction && (
<ReconstructionView reconstruction={result} partial />
)}
</div>
)}
{status === "success" && result?.reconstruction && (
{/* Success state */}
{status === "success" && hasMeaningfulContent && (
<div className="space-y-4">
<ReconstructionView reconstruction={result.reconstruction} />
<DiagnosticsView result={result} />
<ReconstructionView reconstruction={result} />
</div>
)}
{status === "error" && result?.reconstruction && (
<div className="space-y-3">
<div className="rounded-lg border border-yellow-300 bg-yellow-50 px-4 py-2 text-sm text-yellow-800">
Partial result some fields failed validation. Showing what was accepted.
</div>
<ReconstructionView reconstruction={result.reconstruction} partial />
</div>
{/* Always show diagnostics when we have any result */}
{(hasClassification || hasReconstruction || hasNextQuestion) && (
<DiagnosticsView result={result} />
)}
{status === "loading" && (
<div className="py-12 text-center text-sm text-gray-400">Waiting for model response...</div>
<div className="py-12 text-center text-sm text-gray-400">
Waiting for model response...
</div>
)}
{/* Empty state */}
{status === "idle" && (
<div className="rounded-lg border border-dashed border-gray-300 bg-gray-50 px-6 py-8 text-center">
<p className="text-sm text-gray-400">
Enter a scenario above and click Analyse to begin.
</p>
</div>
)}
{/* Invalid result with no partial data */}
{status === "error" && !result?.error && !hasMeaningfulContent && (
<div className="rounded-lg border border-yellow-300 bg-yellow-50 px-4 py-2 text-sm text-yellow-800">
Validation failed no structured output was produced.
</div>
)}
</div>
);