Add MODE=pcb layout exam job with AI and deterministic checks.
Parallel pcb_status pipeline: parse board, classify domains/groups, inventory traces, PE-LAY/PLC/SI/DRT checks, per-IC datasheet review. Findings merge into the report UI. No auto-place or pcbnew write-back.
This commit is contained in:
@@ -110,6 +110,8 @@ function mapProject(p: Record<string, unknown>): Project {
|
||||
netlistSubdesigns: (p.netlist_subdesigns as string[] | null) ?? null,
|
||||
placementStatus: (p.placement_status as Project["placementStatus"]) ?? "draft",
|
||||
placementState: (p.placement_state as Record<string, unknown> | null) ?? null,
|
||||
pcbStatus: (p.pcb_status as Project["pcbStatus"]) ?? "draft",
|
||||
pcbState: (p.pcb_state as Record<string, unknown> | null) ?? null,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -614,6 +616,47 @@ export function placementEventsUrl(projectId: string): string {
|
||||
return `${BASE}/api/pipeline/${projectId}/placement/events`;
|
||||
}
|
||||
|
||||
export async function startPcbPipeline(projectId: string) {
|
||||
const res = await authFetch(
|
||||
`${BASE}/api/pipeline/${projectId}/pcb/start`,
|
||||
{ method: "POST" },
|
||||
);
|
||||
if (!res.ok) {
|
||||
const err = await res.json().catch(() => ({ detail: "Failed to start PCB review" }));
|
||||
throw new Error(err.detail || "Failed to start PCB review");
|
||||
}
|
||||
return res.json();
|
||||
}
|
||||
|
||||
export async function cancelPcbPipeline(projectId: string) {
|
||||
const res = await authFetch(
|
||||
`${BASE}/api/pipeline/${projectId}/pcb/cancel`,
|
||||
{ method: "POST" },
|
||||
);
|
||||
if (!res.ok) {
|
||||
const err = await res.json().catch(() => ({ detail: "Failed to cancel PCB review" }));
|
||||
throw new Error(err.detail || "Failed to cancel PCB review");
|
||||
}
|
||||
return res.json();
|
||||
}
|
||||
|
||||
export function pcbEventsUrl(projectId: string): string {
|
||||
return `${BASE}/api/pipeline/${projectId}/pcb/events`;
|
||||
}
|
||||
|
||||
export async function fetchPcbInventory(projectId: string): Promise<{
|
||||
nets: Array<Record<string, unknown>>;
|
||||
domains: string[];
|
||||
group_count: number;
|
||||
}> {
|
||||
const res = await authFetch(`${BASE}/api/pipeline/${projectId}/pcb/inventory`);
|
||||
if (!res.ok) {
|
||||
const err = await res.json().catch(() => ({ detail: "PCB inventory not found" }));
|
||||
throw new Error(err.detail || "PCB inventory not found");
|
||||
}
|
||||
return res.json();
|
||||
}
|
||||
|
||||
export async function fetchPlacementPlan(projectId: string): Promise<PlacementPlan> {
|
||||
const res = await authFetch(`${BASE}/api/pipeline/${projectId}/placement/plan`);
|
||||
if (!res.ok) {
|
||||
|
||||
@@ -283,6 +283,8 @@ export interface Project {
|
||||
// Placement pipeline (parallel to analysis — topology only).
|
||||
placementStatus?: "draft" | "queued" | "running" | "complete" | "error" | "cancelled";
|
||||
placementState?: Record<string, unknown> | null;
|
||||
pcbStatus?: "draft" | "queued" | "running" | "complete" | "error" | "cancelled";
|
||||
pcbState?: Record<string, unknown> | null;
|
||||
}
|
||||
|
||||
export type RoleHint =
|
||||
|
||||
Reference in New Issue
Block a user