wip: preserve local engine and agent workflow changes before ganjihong refactor integration

This commit is contained in:
2026-09-09 17:08:24 +08:00
parent a5c3ec1f36
commit 387b99e255
112 changed files with 3543 additions and 12177 deletions
+12 -38
View File
@@ -21,7 +21,7 @@ import type {
} from "@/lib/cad-types";
import { AgentThread } from "./agent-thread";
import { CadViewerPreview } from "./cad-viewer-preview";
import { MarkdownDocument } from "./rich-content";
import { JsonTree, MarkdownDocument } from "./rich-content";
import type { AssistantRuntime } from "@assistant-ui/react";
type LoadState = "loading" | "ready" | "error";
@@ -557,27 +557,10 @@ function StudioShell({
</div>
</header>
{!config?.configured ? <div className="config-warning"><AlertCircle size={16} /><span></span></div> : null}
{config?.autonomous_generation && !config.review_configured ? <div className="config-warning"><AlertCircle size={16} /><span>{config.review_error || "请配置独立视觉模型。"}</span></div> : null}
<div className="studio-main">
<aside className="agent-pane">
<AgentThread attachments={attachments} uploading={uploading} uploadError={uploadError} taskRunning={taskRunning} onUpload={onUpload} onCancel={onCancel} />
<TaskDocuments task={taskRecord} onSelectRevision={(revisionId) => {
const revision = taskRecord?.revisions.find((item) => item.revision_id === revisionId);
if (!revision?.cdsl_path || !revision.step_path || !revision.glb_path || !revision.report_path || !taskRecord) return;
onCadResult({
taskId: taskRecord.task_id,
revisionId,
cdslPath: revision.cdsl_path,
stepPath: revision.step_path,
glbPath: revision.glb_path,
reportPath: revision.report_path,
summary: revision.summary || "CDSL CAD model",
referenceIds: revision.reference_ids || [],
engine: revision.engine || "cdsl_only",
checkpoint: revision.visibility === "checkpoint",
lifecycle: taskRecord.lifecycle || "running",
});
}} />
<TaskDocuments task={taskRecord} />
</aside>
<section className="preview-pane">
<CadViewerPreview result={cadResult} isGenerating={running} lastError={lastError} theme={theme} onError={handleViewerError} onSelectionChange={onSelectionChange} />
@@ -587,27 +570,18 @@ function StudioShell({
);
}
function TaskDocuments({ task, onSelectRevision }: { task: TaskRecord | null; onSelectRevision: (revisionId: string) => void }) {
const documents = [
["需求文档", task?.requirements_markdown],
["完成目标", task?.completion_target_markdown],
function TaskDocuments({ task }: { task: TaskRecord | null }) {
const structured = [
["需求分析", task?.requirements_analysis],
["Authoring CDSL", task?.authoring_cdsl],
["编译审计", task?.compile_audit],
["构建诊断", task?.diagnostics],
] as const;
if (!documents.some(([, markdown]) => markdown) && !task?.feature_nodes?.length) return null;
if (!structured.some(([, value]) => value) && !task?.completion_result_markdown) return null;
return <section className="task-documents" aria-label="任务文档">
{task?.checklist_progress?.length ? <div className="task-checklist" aria-label="验收进度">
{task.checklist_progress.map((item) => <div key={item.requirement_id || item.statement} className={`task-checklist-item is-${item.status}`}><span>{item.status === "pass" ? "完成" : item.status === "fail" ? "未通过" : "待验证"}</span>{item.statement}</div>)}
</div> : null}
{task?.feature_nodes?.length ? <details open className="task-document" aria-label="特征 DAG">
<summary> DAG</summary>
<div className="task-checklist">
{task.feature_nodes.slice().sort((a, b) => (a.priority ?? 0) - (b.priority ?? 0)).map((node) => <div key={node.node_id} className={`task-checklist-item is-${node.status || "pending"}`}>
<span>{node.status === "done" ? "完成" : node.status === "running" ? "执行中" : node.status === "failed" ? "失败" : node.status === "blocked" ? "阻塞" : "待执行"}</span>
<div><strong>{node.intent || node.node_id}</strong><small>{node.atomic_id} · {node.priority}{node.depends_on?.length ? ` · 依赖 ${node.depends_on.join(", ")}` : ""}{node.attempt ? ` · 尝试 ${node.attempt}` : ""}</small>{node.error ? <small>{node.error}</small> : null}</div>
{node.status === "done" && node.revision_id ? <button type="button" title="查看此特征检查点" onClick={() => onSelectRevision(node.revision_id!)}></button> : null}
</div>)}
</div>
</details> : null}
{documents.map(([title, markdown]) => markdown ? <details key={title} className="task-document"><summary>{title}</summary><MarkdownDocument>{markdown}</MarkdownDocument></details> : null)}
{task?.repair_count !== undefined ? <div className="task-checklist"><div className="task-checklist-item"><span></span><div>{task.repair_count} / {task.repair_budget ?? 2}</div></div></div> : null}
{structured.map(([title, value]) => value ? <details key={title} className="task-document"><summary>{title}</summary><JsonTree data={value} /></details> : null)}
{task?.completion_result_markdown ? <details className="task-document" open><summary></summary><MarkdownDocument>{task.completion_result_markdown}</MarkdownDocument></details> : null}
</section>;
}
+4 -12
View File
@@ -1,9 +1,9 @@
"use client";
import { AlertTriangle, Box, Check, Download, Eye, FileCheck, Loader2, RotateCcw, Search, Wrench } from "lucide-react";
import { AlertTriangle, Box, Check, Download, FileCheck, Loader2, RotateCcw, Search } from "lucide-react";
import { encodeArtifactUrl } from "@/lib/cad-artifacts";
import type { CadError, CadProgress, CadResult } from "@/lib/cad-types";
import { JsonTree, MarkdownDocument } from "./rich-content";
import { MarkdownDocument } from "./rich-content";
export function TextPart({ text }: { text: string }) {
if (!text.trim()) return null;
@@ -15,26 +15,20 @@ export function CadProgressPart({ data }: { data: CadProgress }) {
const isRunning = status === "running";
const isError = status === "error";
const isWaiting = status === "waiting";
const statusLabel = isRunning ? "进行中" : isWaiting ? data.lifecycle === "waiting_retry" ? "等待重试" : "等待确认" : isError ? "失败" : status === "success" ? "完成" : data.status;
const Icon = data.step === "tool_call" ? Wrench : data.step.includes("review") || data.step === "final_review" ? Eye : data.step === "rollback" ? RotateCcw : data.step.includes("requirements") || data.step.includes("checklist") ? FileCheck : data.step.includes("diagnostic") ? Search : isError || isWaiting ? AlertTriangle : Check;
const evidence = data.evidence || (Array.isArray(data.review?.evidence) ? data.review.evidence.map(String) : []);
const statusLabel = isRunning ? "进行中" : isWaiting ? "等待确认" : isError ? "失败" : status === "success" ? "完成" : data.status;
const Icon = data.step === "repair_started" ? RotateCcw : data.step === "build_result" ? Box : data.step === "cdsl_compiled" ? Search : data.step === "requirements_ready" || data.step === "authoring_cdsl_ready" ? FileCheck : isError || isWaiting ? AlertTriangle : Check;
const documentMarkdown = data.markdown || "";
return (
<div className={`cad-message cad-progress${isError ? " is-error" : ""}${isWaiting ? " is-waiting" : ""}`} role="status" aria-live="polite">
<div className="cad-message-heading">
{isRunning ? <Loader2 className="spin" size={14} aria-hidden="true" /> : <Icon size={14} aria-hidden="true" />}
<span>{data.label || data.step}</span>
{data.tool ? <code className="cad-tool-name">{data.tool}</code> : null}
<span className="cad-status-label">{statusLabel}</span>
</div>
{data.message ? <div className="cad-message-copy">{data.message}</div> : null}
{data.questions?.length ? <ul className="cad-waiting-questions">{data.questions.map((question, index) => <li key={`${question}-${index}`}>{question}</li>)}</ul> : null}
{data.issues?.length ? <ul className="cad-waiting-questions">{data.issues.map((issue, index) => <li key={`${issue}-${index}`}>{issue}</li>)}</ul> : null}
{data.verificationWarnings?.length ? <details className="cad-event-details" open><summary> ({data.verificationWarnings.length})</summary><ul>{data.verificationWarnings.map((warning, index) => <li key={`${warning}-${index}`}>{warning}</li>)}</ul></details> : null}
{documentMarkdown ? <details className="cad-event-details cad-document-details"><summary></summary><MarkdownDocument>{documentMarkdown}</MarkdownDocument></details> : null}
{data.arguments ? <details className="cad-event-details"><summary></summary><JsonTree data={data.arguments} /></details> : null}
{data.result !== undefined ? <details className="cad-event-details"><summary></summary><JsonTree data={data.result} /></details> : null}
{evidence.length ? <details className="cad-event-details"><summary> ({evidence.length})</summary><ul>{evidence.map((item, index) => <li key={`${item}-${index}`}>{item}</li>)}</ul></details> : null}
</div>
);
}
@@ -59,7 +53,6 @@ export function CadResultPart({ data }: { data: CadResult }) {
<span>{data.referenceIds.length} </span>
</div>
{data.referenceIds.length ? <div className="cad-result-notes"><strong></strong><span>{data.referenceIds.join("")}</span></div> : null}
{data.verificationWarnings?.length ? <div className="cad-result-notes"><strong></strong><span>{data.verificationWarnings.join("")}</span></div> : null}
{downloads.length ? <div className="download-row">
{downloads.map(([label, path]) => (
<a key={label} className="download-link" href={encodeArtifactUrl(data.taskId, path)} download aria-label={`下载 ${label}`}>
@@ -84,7 +77,6 @@ export function CadErrorPart({ data }: { data: CadError }) {
<div className="cad-message cad-error" role="alert">
<div className="cad-message-heading"><AlertTriangle size={14} aria-hidden="true" /><span>{stage}</span></div>
<div className="cad-message-copy">{data.message}</div>
{data.tool ? <code className="cad-tool-name">{data.tool}</code> : null}
{data.fieldErrors?.length ? <details className="cad-event-details" open><summary> ({data.fieldErrors.length})</summary><ul>{data.fieldErrors.map((error, index) => <li key={`${error.path || "field"}-${index}`}><code>{error.path || "/"}</code>{error.message ? `: ${error.message}` : ""}</li>)}</ul></details> : null}
</div>
);
+1 -6
View File
@@ -30,8 +30,6 @@ function resultForRevision(task: TaskRecord, revisionId: string, checkpoint: boo
engine: current.engine || "cdsl_only",
checkpoint,
lifecycle: task.lifecycle || "completed",
verificationStatus: task.verification_status,
verificationWarnings: task.verification_warnings || [],
};
}
@@ -44,10 +42,7 @@ export function activeCheckpointPreview(task: TaskRecord | null): CadResult | nu
export function latestSuccessfulResult(task: TaskRecord | null): CadResult | null {
if (!task) return null;
// v3.2 deliberately exposes its last verified checkpoint on a failed DAG:
// failure means requirements were not completed, not that earlier geometry
// should disappear. Legacy task projections retain the former policy.
if (task.lifecycle === "failed" && !task.published_revision && task.schema_version !== "3.2") return null;
if (task.lifecycle === "failed" && !task.published_revision) return null;
const current =
task.revisions.find((revision) => revision.revision_id === (task.published_revision || task.current_revision)) ??
[...task.revisions].reverse().find((revision) => revision.status === "success" && revision.visibility !== "checkpoint");
+1 -4
View File
@@ -62,7 +62,7 @@ export function restoreTaskProjection(messages: CadUIMessage[], task: TaskRecord
));
if (alreadyVisible) return messages;
const status = task.lifecycle === "failed" ? "error"
: task.lifecycle === "waiting_for_user" || task.lifecycle === "waiting_retry" ? "waiting"
: task.lifecycle === "waiting_for_user" ? "waiting"
: task.lifecycle === "completed" ? "success" : "running";
const progress: CadProgress = {
step,
@@ -73,10 +73,7 @@ export function restoreTaskProjection(messages: CadUIMessage[], task: TaskRecord
message: task.message || (terminal ? "CAD 任务已停止。" : "CAD 任务正在运行。"),
questions: task.questions || [],
issues: task.issues || [],
blockerType: task.blocker_type,
userActionRequired: Boolean(task.user_action_required),
verificationStatus: task.verification_status,
verificationWarnings: task.verification_warnings || [],
};
return [...messages, {
id: `projection_${task.task_id}_${task.state_version || 0}`,
+21 -38
View File
@@ -9,10 +9,18 @@ import type { CadUIMessage } from "./cad-types";
test("maps backend cad_result SSE into an AI SDK data part", () => {
const chunk = backendEventToUiChunk({
event: "cad_result",
data: { taskId: "cad_abc", revisionId: "rev_001" },
data: {
taskId: "cad_abc", revisionId: "rev_001", cdslPath: "model.cdsl.json",
stepPath: "model.step", glbPath: "model.glb", reportPath: "rebuild-report.json",
summary: "plate", referenceIds: [], engine: "cdsl_only",
},
}, "text_1");
assert.equal(chunk?.type, "data-cad-result");
assert.deepEqual("data" in chunk! ? chunk.data : null, { taskId: "cad_abc", revisionId: "rev_001" });
assert.deepEqual("data" in chunk! ? chunk.data : null, {
taskId: "cad_abc", revisionId: "rev_001", cdslPath: "model.cdsl.json",
stepPath: "model.step", glbPath: "model.glb", reportPath: "rebuild-report.json",
summary: "plate", referenceIds: [], engine: "cdsl_only",
});
});
test("keeps progressive revisions as separate data parts", () => {
@@ -21,23 +29,13 @@ test("keeps progressive revisions as separate data parts", () => {
assert.notEqual(first?.id, second?.id);
});
test("maps final repair review into a blocking progress state", () => {
test("maps a single-stage build repair into a blocking progress state", () => {
const chunk = backendEventToUiChunk({
event: "final_review", data: { taskId: "cad_abc", result: { status: "repair", evidence: ["missing round"] } },
event: "build_result", data: { taskId: "cad_abc", status: "repair_required", message: "host face is ambiguous" },
}, "text_1");
assert.equal(chunk?.type, "data-cad-progress");
assert.deepEqual("data" in chunk! ? chunk.data : null, {
step: "final_review", label: "最终独立复核", status: "error", message: "", taskId: "cad_abc", result: { status: "repair", evidence: ["missing round"] },
});
});
test("maps a rejected independent candidate review into a blocking progress state", () => {
const chunk = backendEventToUiChunk({
event: "candidate_review", data: { taskId: "cad_abc", result: { status: "rejected", evidence: ["base is disconnected"] } },
}, "text_1");
assert.equal(chunk?.type, "data-cad-progress");
assert.deepEqual("data" in chunk! ? chunk.data : null, {
step: "candidate_review", label: "候选独立复核", status: "error", message: "", taskId: "cad_abc", result: { status: "rejected", evidence: ["base is disconnected"] },
step: "build_result", label: "CAD 构建", status: "error", message: "host face is ambiguous", taskId: "cad_abc",
});
});
@@ -46,7 +44,7 @@ test("keeps terminal schema field errors visible to the CAD error part", () => {
event: "cad_error",
data: {
stage: "generation",
tool: "compile_requirements_spec",
tool: "write_authoring_cdsl",
message: "Author repeatedly failed the schema.",
fieldErrors: [{ path: "/patches", message: "Field required" }],
},
@@ -54,7 +52,7 @@ test("keeps terminal schema field errors visible to the CAD error part", () => {
assert.equal(chunk?.type, "data-cad-error");
assert.deepEqual("data" in chunk! ? chunk.data : null, {
stage: "generation",
tool: "compile_requirements_spec",
tool: "write_authoring_cdsl",
message: "Author repeatedly failed the schema.",
fieldErrors: [{ path: "/patches", message: "Field required" }],
});
@@ -124,17 +122,17 @@ test("keeps explicit runtime issues visible when generation stops", () => {
});
});
test("gives repeated tool events unique ordered parts", () => {
const first = backendEventToUiChunk({ event: "tool_call", data: { taskId: "cad_abc", tool: "inspect_model", status: "running" } }, "text_1", 4);
const second = backendEventToUiChunk({ event: "tool_call", data: { taskId: "cad_abc", tool: "inspect_model", status: "success" } }, "text_1", 5);
test("gives repeated build events unique ordered parts", () => {
const first = backendEventToUiChunk({ event: "build_result", data: { taskId: "cad_abc", status: "repair_required" } }, "text_1", 4);
const second = backendEventToUiChunk({ event: "build_result", data: { taskId: "cad_abc", status: "completed" } }, "text_1", 5);
assert.notEqual(first?.id, second?.id);
assert.equal("data" in first! ? (first.data as { sequence?: number }).sequence : null, 4);
assert.equal("data" in second! ? (second.data as { sequence?: number }).sequence : null, 5);
});
test("reuses an invocation id so tool completion updates its running card", () => {
const running = backendEventToUiChunk({ event: "tool_call", data: { taskId: "cad_abc", eventId: "call_1", invocationId: "call_1", tool: "submit_cdsl_fragment", status: "running" } }, "text_1", 4);
const complete = backendEventToUiChunk({ event: "tool_call", data: { taskId: "cad_abc", eventId: "call_1", invocationId: "call_1", tool: "submit_cdsl_fragment", status: "success" } }, "text_1", 5);
test("reuses an event id for build card updates", () => {
const running = backendEventToUiChunk({ event: "build_result", data: { taskId: "cad_abc", eventId: "build_1", status: "repair_required" } }, "text_1", 4);
const complete = backendEventToUiChunk({ event: "build_result", data: { taskId: "cad_abc", eventId: "build_1", status: "completed" } }, "text_1", 5);
assert.equal(running?.id, complete?.id);
});
@@ -180,21 +178,6 @@ test("does not restore a private checkpoint after a failed run", () => {
assert.equal(result, null);
});
test("restores the last verified v3.2 DAG checkpoint after a failed run", () => {
const result = latestSuccessfulResult({
schema_version: "3.2",
task_id: "cad_abc",
current_revision: "rev_002",
active_revision: "rev_002",
lifecycle: "failed",
revisions: [
{ revision_id: "rev_002", status: "success", visibility: "checkpoint", cdsl_path: "aa", step_path: "bb", glb_path: "cc", report_path: "dd" },
],
});
assert.equal(result?.revisionId, "rev_002");
assert.equal(result?.checkpoint, true);
});
test("restores an active checkpoint only while the task is running", () => {
const result = activeCheckpointPreview({
task_id: "cad_abc", current_revision: "rev_002", active_revision: "rev_002", published_revision: "rev_001", lifecycle: "running",
+5 -21
View File
@@ -20,15 +20,11 @@ export function backendEventToUiChunk(
data: { ...item.data, sequence },
};
}
if (["image_observation", "requirements_document_ready", "completion_target_ready", "requirements_compiled", "modeling_plan_ready", "completion_result_ready", "action_selection", "tool_call", "candidate_result", "candidate_review", "final_review", "task_terminal"].includes(item.event)) {
const review = item.data.review && typeof item.data.review === "object"
? item.data.review as Record<string, unknown>
: null;
if (["requirements_ready", "authoring_cdsl_ready", "cdsl_compiled", "build_result", "repair_started", "task_terminal"].includes(item.event)) {
const lifecycle = String(item.data.lifecycle || "");
const status = item.event === "task_terminal"
? (lifecycle === "failed" ? "error" : lifecycle === "waiting_for_user" || lifecycle === "waiting_retry" ? "waiting" : "success")
: String((item.data.result as Record<string, unknown> | undefined)?.status || "") === "rejected"
|| String((item.data.result as Record<string, unknown> | undefined)?.status || "") === "repair"
? (lifecycle === "failed" ? "error" : lifecycle === "waiting_for_user" ? "waiting" : "success")
: String(item.data.status || "") === "repair_required"
? "error"
: String(item.data.status || "running");
const taskId = String(item.data.taskId || "task");
@@ -37,37 +33,25 @@ export function backendEventToUiChunk(
? {
eventId,
sequence,
...(review ? { review } : {}),
}
: {};
return {
type: "data-cad-progress",
id: `event_${eventId}`,
data: { step: item.event, label: ({
image_observation: "参考图片观察", requirements_document_ready: "需求文档已冻结", completion_target_ready: "完成目标已冻结", requirements_compiled: "需求合同已编译", modeling_plan_ready: "建模计划已冻结", completion_result_ready: "完成结果已就绪", action_selection: "动作选择", tool_call: "建模工具", candidate_result: "候选构建", candidate_review: "候选独立复核", final_review: "最终独立复核", task_terminal: "生成任务",
requirements_ready: "需求分析", authoring_cdsl_ready: "完整 CDSL", cdsl_compiled: "CDSL 编译", build_result: "CAD 构建", repair_started: "CDSL 修复", task_terminal: "生成任务",
} as Record<string, string>)[item.event], status, ...metadata, message: String(
item.data.message || item.data.reason
|| (Array.isArray(item.data.questions) ? item.data.questions.map(String).filter(Boolean).join("") : "")
|| (review?.evidence instanceof Array ? review.evidence.join("") : "")
|| (review?.issues instanceof Array ? review.issues.map((issue) => typeof issue === "object" && issue ? String((issue as Record<string, unknown>).message || "") : String(issue)).filter(Boolean).join("") : ""),
|| (Array.isArray(item.data.questions) ? item.data.questions.map(String).filter(Boolean).join("") : ""),
),
...(item.data.taskId ? { taskId } : {}),
...(item.data.nodeId ? { nodeId: String(item.data.nodeId) } : {}),
...(item.data.lifecycle ? { lifecycle: String(item.data.lifecycle) } : {}),
...(Array.isArray(item.data.questions) ? { questions: item.data.questions.map(String).filter(Boolean) } : {}),
...(Array.isArray(item.data.issues) ? { issues: item.data.issues.map(String).filter(Boolean) } : {}),
...(item.data.blockerType ? { blockerType: String(item.data.blockerType) } : {}),
...(typeof item.data.userActionRequired === "boolean" ? { userActionRequired: item.data.userActionRequired } : {}),
...(item.data.verificationStatus ? { verificationStatus: String(item.data.verificationStatus) } : {}),
...(Array.isArray(item.data.verificationWarnings) ? { verificationWarnings: item.data.verificationWarnings.map(String).filter(Boolean) } : {}),
...(item.data.clarificationPath ? { clarificationPath: String(item.data.clarificationPath) } : {}),
...(item.data.timestamp ? { timestamp: String(item.data.timestamp) } : {}),
...(item.data.markdown ? { markdown: String(item.data.markdown) } : {}),
...(item.data.tool ? { tool: String(item.data.tool) } : {}),
...(item.data.invocationId ? { invocationId: String(item.data.invocationId) } : {}),
...(item.data.arguments && typeof item.data.arguments === "object" ? { arguments: item.data.arguments as Record<string, unknown> } : {}),
...(item.data.result !== undefined ? { result: item.data.result } : {}),
...(Array.isArray(item.data.evidence) ? { evidence: item.data.evidence.map(String) } : {}),
},
};
}
+18 -78
View File
@@ -10,25 +10,12 @@ export type CadProgress = {
message?: string;
markdown?: string;
taskId?: string;
nodeId?: string;
tool?: string;
invocationId?: string;
arguments?: Record<string, unknown>;
result?: unknown;
evidence?: string[];
questions?: string[];
issues?: string[];
blockerType?: string;
userActionRequired?: boolean;
verificationStatus?: "verified" | "completed_with_risks" | string;
verificationWarnings?: string[];
review?: Record<string, unknown>;
clarificationPath?: string;
lifecycle?: "running" | "completed" | "failed" | "waiting_retry" | "waiting_for_user" | string;
attempt?: number;
maxAttempts?: number;
lifecycle?: "running" | "completed" | "failed" | "waiting_for_user" | string;
path?: string;
contractHash?: string;
};
export type CadResult = {
@@ -43,8 +30,6 @@ export type CadResult = {
engine: string;
checkpoint?: boolean;
lifecycle?: "running" | "completed" | "failed" | string;
verificationStatus?: "verified" | "completed_with_risks" | string;
verificationWarnings?: string[];
};
export type CadError = {
@@ -97,12 +82,6 @@ export type TaskRevision = {
engine?: string;
error?: string;
visibility?: "checkpoint" | "final" | "superseded" | string;
parent_revision_id?: string;
branch_id?: string;
step_review_path?: string;
candidate_review_path?: string;
render_manifest_path?: string;
visual_review_path?: string;
};
export type TaskRecord = {
@@ -111,71 +90,34 @@ export type TaskRecord = {
current_revision: string;
active_revision?: string;
published_revision?: string;
lifecycle?: "running" | "completed" | "failed" | "cancelled" | "waiting_retry" | "waiting_for_user" | string;
lifecycle?: "running" | "completed" | "failed" | "cancelled" | "waiting_for_user" | string;
phase?: string;
state_version?: number;
active_candidate_id?: string;
requirements_spec?: Record<string, unknown> | null;
requirements_spec_path?: string;
repair_count?: number;
repair_budget?: number;
requirements_path?: string;
authoring_path?: string;
runtime_cdsl_path?: string;
compile_audit_path?: string;
diagnostics_path?: string;
completion_path?: string;
clarification_path?: string;
requirements_contract?: Record<string, unknown> | null;
requirements_contract_path?: string;
requirements_markdown?: string | null;
requirements_document_path?: string;
completion_target_markdown?: string | null;
completion_target_path?: string;
feature_plan?: {
requirements_analysis?: Record<string, unknown> | null;
authoring_cdsl?: Record<string, unknown> | null;
runtime_cdsl?: Record<string, unknown> | null;
compile_audit?: Record<string, unknown> | null;
diagnostics?: Record<string, unknown> | null;
claim_report?: {
schema_version?: string;
parent_plan_hash?: string;
replaces_node_ids?: string[];
nodes?: Array<Record<string, unknown>>;
final_claim_ids?: string[];
claims?: Array<{ target?: string; status?: "pass" | "fail" | "pending" | "not_applicable" | string; verification?: string }>;
} | null;
feature_plan_path?: string;
feature_plan_hash?: string;
current_feature_node_id?: string;
pending_feature?: { action_id: string; node_id: string; plan_hash: string; atomic_id: string; claim_ids: string[]; depends_on_node_ids: string[] } | null;
feature_nodes?: Array<{
node_id: string;
intent?: string;
atomic_id?: string;
priority?: number;
depends_on?: string[];
claim_ids?: string[];
status?: "pending" | "ready" | "running" | "done" | "failed" | "blocked" | "invalidated" | string;
attempt?: number;
failure_class?: string;
error?: string;
revision_id?: string;
feature_id?: string;
evidence?: Array<Record<string, unknown>>;
}>;
completion_result_markdown?: string | null;
completion_result_path?: string;
claim_summary?: Array<{
requirement_id: string;
claim_id: string;
claim_kind: string;
deterministic: boolean;
status: "pass" | "pending" | "fail" | "unavailable" | string;
evidence?: Record<string, unknown>;
}>;
checklist_progress?: Array<{
requirement_id: string;
statement: string;
status: "pass" | "pending" | "fail" | string;
}>;
pending_action?: { action_id: string; working_head: string; intent: string; requirement_ids: string[]; atomic_id: string; expected_change: string; contract_hash: string } | null;
action_ledger_summary?: Array<Record<string, unknown>>;
usage?: { calls: number; prompt_tokens: number; completion_tokens: number; context_chars: number };
usage?: { calls: number; records: Array<Record<string, unknown>> };
preview_revision?: string;
message?: string;
questions?: string[];
issues?: string[];
blocker_type?: string;
user_action_required?: boolean;
verification_status?: "verified" | "completed_with_risks" | string;
verification_warnings?: string[];
revisions: TaskRevision[];
};
@@ -191,6 +133,4 @@ export type BackendConfig = {
configured: boolean;
library_samples: number;
autonomous_generation?: boolean;
review_configured?: boolean;
review_error?: string;
};