{"openapi":"3.1.0","info":{"title":"iRush PCB Agent","description":"Upload Gerber/Excellon files (or a zip) and get back PCB specifications, DFM review and 2D renders.","version":"0.1.0"},"paths":{"/api/v1/health":{"get":{"summary":"Health","operationId":"health_api_v1_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Health Api V1 Health Get"}}}}}}},"/api/v1/agents":{"get":{"summary":"List Agents","description":"The sub-agents of this service (Gerber extractor, DRC, inspector, renderer, quote, assembly, BOM...): what\neach consumes and produces, which routes expose it, and its model status when it can be trained.","operationId":"list_agents_api_v1_agents_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/AgentInfo"},"type":"array","title":"Response List Agents Api V1 Agents Get"}}}}}}},"/api/v1/agents/{name}":{"get":{"summary":"Agent Info","operationId":"agent_info_api_v1_agents__name__get","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentInfo"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/jobs/{job_id}/agents/{name}/run":{"post":{"summary":"Run Agent","description":"Run one sub-agent on an existing job and get its output - the generic way for any application to use a\ncapability (e.g. `quote` with {\"units\": \"mil\"}, `drc` with {\"fresh\": \"true\"}, `bom`, `assembly`, `inspector`).","operationId":"run_agent_api_v1_jobs__job_id__agents__name__run_post","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}},{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"type":"object","additionalProperties":{"type":"string"}},{"type":"null"}],"title":"Params"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Run Agent Api V1 Jobs  Job Id  Agents  Name  Run Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/agents/{name}/run":{"post":{"summary":"Run Agent Standalone","description":"Run a sub-agent that needs no board job (e.g. `company` with {\"name\": \"Acme PCB\"}) through the primary agent.","operationId":"run_agent_standalone_api_v1_agents__name__run_post","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"type":"object","additionalProperties":true},{"type":"null"}],"title":"Params"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Run Agent Standalone Api V1 Agents  Name  Run Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/agents/{name}/train":{"post":{"summary":"Train Agent","description":"Train a sub-agent that has a model (today: `quote`). Each sub-agent trains on its own dataset.","operationId":"train_agent_api_v1_agents__name__train_post","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}},{"name":"n_synthetic","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":4000,"title":"N Synthetic"}},{"name":"real_only","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Real Only"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Train Agent Api V1 Agents  Name  Train Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/jobs/{job_id}/provenance":{"get":{"summary":"Job Provenance","description":"Which sub-agent version produced each part of the job, with timings.","operationId":"job_provenance_api_v1_jobs__job_id__provenance_get","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Provenance"},"title":"Response Job Provenance Api V1 Jobs  Job Id  Provenance Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/bom/validate":{"post":{"summary":"Bom Validate","description":"BOM agent on its own: parse and validate a BOM without Gerbers (for the BOM / sourcing screens).","operationId":"bom_validate_api_v1_bom_validate_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_bom_validate_api_v1_bom_validate_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Bom Validate Api V1 Bom Validate Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/pnp/parse":{"post":{"summary":"Pnp Parse","description":"Centroid parser on its own: format, unit, columns and placements (for previews and format checks).","operationId":"pnp_parse_api_v1_pnp_parse_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_pnp_parse_api_v1_pnp_parse_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Pnp Parse Api V1 Pnp Parse Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/analyze":{"post":{"summary":"Analyze","operationId":"analyze_api_v1_analyze_post","parameters":[{"name":"review","in":"query","required":false,"schema":{"enum":["local","llm","none"],"type":"string","description":"local = rules + ML (offline, default); llm = Claude; none = metrics only","default":"local","title":"Review"},"description":"local = rules + ML (offline, default); llm = Claude; none = metrics only"},{"name":"renders","in":"query","required":false,"schema":{"enum":["lazy","inline"],"type":"string","description":"lazy: fetch SVGs from the render endpoint; inline: embed all SVGs in the response","default":"lazy","title":"Renders"},"description":"lazy: fetch SVGs from the render endpoint; inline: embed all SVGs in the response"},{"name":"board","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"When the upload holds several boards, which one to analyse (see other_boards)","title":"Board"},"description":"When the upload holds several boards, which one to analyse (see other_boards)"}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_analyze_api_v1_analyze_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnalysisResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/assembly":{"post":{"summary":"Analyze Assembly","description":"Same analysis as /analyze (one job, one store), answered with the assembly view: footprints from the Gerbers,\nplacements aligned and cross-referenced with the BOM, DFA findings and the assembly summary.","operationId":"analyze_assembly_api_v1_assembly_post","parameters":[{"name":"board","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Board"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_analyze_assembly_api_v1_assembly_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssemblyResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/jobs/{job_id}/assembly":{"get":{"summary":"Get Assembly","description":"Assembly view of a job (footprints only until a centroid file / BOM is attached).","operationId":"get_assembly_api_v1_jobs__job_id__assembly_get","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssemblyResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/jobs/{job_id}/assembly/files":{"post":{"summary":"Add Assembly Files","operationId":"add_assembly_files_api_v1_jobs__job_id__assembly_files_post","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_add_assembly_files_api_v1_jobs__job_id__assembly_files_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssemblyResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/jobs/{job_id}/files":{"post":{"summary":"Add Job Files","description":"Add files to an existing job and re-analyse everything together. Same-named files are replaced.","operationId":"add_job_files_api_v1_jobs__job_id__files_post","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}},{"name":"review","in":"query","required":false,"schema":{"enum":["local","llm","none"],"type":"string","default":"local","title":"Review"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_add_job_files_api_v1_jobs__job_id__files_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnalysisResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/jobs":{"get":{"summary":"List Jobs","operationId":"list_jobs_api_v1_jobs_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/JobSummary"},"type":"array","title":"Response List Jobs Api V1 Jobs Get"}}}}}}},"/api/v1/jobs/{job_id}":{"get":{"summary":"Get Job","operationId":"get_job_api_v1_jobs__job_id__get","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnalysisResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/quote/settings":{"get":{"summary":"Get Quote Settings","description":"Per-spec fill policy for rows the files do not answer (prefill a default / leave empty).","operationId":"get_quote_settings_api_v1_quote_settings_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuoteSettings"}}}}}},"put":{"summary":"Put Quote Settings","operationId":"put_quote_settings_api_v1_quote_settings_put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuoteSettings"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuoteSettings"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/jobs/{job_id}/quote":{"get":{"summary":"Get Quote","description":"The 65 quote rows with the current quote settings applied (what the xlsx will contain).","operationId":"get_quote_api_v1_jobs__job_id__quote_get","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}},{"name":"units","in":"query","required":false,"schema":{"anyOf":[{"enum":["mm","mil","inch"],"type":"string"},{"type":"null"}],"description":"Length unit; default = the quote settings' preference","title":"Units"},"description":"Length unit; default = the quote settings' preference"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/QuoteRow"},"title":"Response Get Quote Api V1 Jobs  Job Id  Quote Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/jobs/{job_id}/documents/{file}/pages/{page}.png":{"get":{"summary":"Document Page","description":"A page of an uploaded sketch / fab drawing (PDF or image) rendered as PNG, for the document viewer.","operationId":"document_page_api_v1_jobs__job_id__documents__file__pages__page__png_get","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}},{"name":"file","in":"path","required":true,"schema":{"type":"string","title":"File"}},{"name":"page","in":"path","required":true,"schema":{"type":"integer","title":"Page"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/jobs/{job_id}/quote.xlsx":{"get":{"summary":"Quote Xlsx","description":"The customer quote sheet (specifications template) filled from this job, as an Excel download.","operationId":"quote_xlsx_api_v1_jobs__job_id__quote_xlsx_get","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}},{"name":"units","in":"query","required":false,"schema":{"anyOf":[{"enum":["mm","mil","inch"],"type":"string"},{"type":"null"}],"title":"Units"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/jobs/{job_id}/render/{layer_key}.svg":{"get":{"summary":"Get Render","description":"Render a layer on demand and serve it as an SVG document (usable in <img src=...>).\n\n`layer_key` is `top`, `bottom`, or a layer key with the space replaced by `_` (e.g. `top_copper`).","operationId":"get_render_api_v1_jobs__job_id__render__layer_key__svg_get","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}},{"name":"layer_key","in":"path","required":true,"schema":{"type":"string","title":"Layer Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/jobs/{job_id}/image/{kind}/{side}.png":{"get":{"summary":"Get Image","description":"Rendered board images: `3d` = isometric slab view, `photo` = realistic top-down composite.","operationId":"get_image_api_v1_jobs__job_id__image__kind___side__png_get","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}},{"name":"kind","in":"path","required":true,"schema":{"enum":["3d","photo"],"type":"string","title":"Kind"}},{"name":"side","in":"path","required":true,"schema":{"enum":["top","bottom"],"type":"string","title":"Side"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/jobs/{job_id}/layer/{layer_key}.png":{"get":{"summary":"Get Layer Image","description":"Anti-aliased layer image. `layer` = RGBA in the layer's CAM colour (stack them), `single` = flattened\nview with board base and drills, `base` = board base only (`layer_key` ignored). Keys use '_' for ' '.","operationId":"get_layer_image_api_v1_jobs__job_id__layer__layer_key__png_get","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}},{"name":"layer_key","in":"path","required":true,"schema":{"type":"string","title":"Layer Key"}},{"name":"mode","in":"query","required":false,"schema":{"enum":["layer","single","base"],"type":"string","default":"layer","title":"Mode"}},{"name":"max","in":"query","required":false,"schema":{"type":"integer","maximum":4096,"minimum":256,"description":"longest side in px (3D textures use ~1536)","default":3000,"title":"Max"},"description":"longest side in px (3D textures use ~1536)"},{"name":"palette","in":"query","required":false,"schema":{"enum":["cam","real"],"type":"string","description":"'real' = material colours (copper / mask / legend) for the 3D layers view","default":"cam","title":"Palette"},"description":"'real' = material colours (copper / mask / legend) for the 3D layers view"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/jobs/{job_id}/view.png":{"get":{"summary":"Get View","description":"Render the viewport (x0,y0)-(x1,y1) mm at w x h px. Sharp at any zoom; used by the canvas viewer.","operationId":"get_view_api_v1_jobs__job_id__view_png_get","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}},{"name":"mode","in":"query","required":false,"schema":{"enum":["cam","photo"],"type":"string","default":"cam","title":"Mode"}},{"name":"keys","in":"query","required":false,"schema":{"type":"string","description":"comma-separated layer keys for mode=cam (spaces as '_')","default":"","title":"Keys"},"description":"comma-separated layer keys for mode=cam (spaces as '_')"},{"name":"side","in":"query","required":false,"schema":{"enum":["top","bottom"],"type":"string","default":"top","title":"Side"}},{"name":"drills","in":"query","required":false,"schema":{"type":"boolean","description":"mode=cam: overlay all drill layers","default":false,"title":"Drills"},"description":"mode=cam: overlay all drill layers"},{"name":"alpha","in":"query","required":false,"schema":{"type":"boolean","description":"mode=photo: transparent outside the board (for 3D textures)","default":false,"title":"Alpha"},"description":"mode=photo: transparent outside the board (for 3D textures)"},{"name":"x0","in":"query","required":true,"schema":{"type":"number","title":"X0"}},{"name":"y0","in":"query","required":true,"schema":{"type":"number","title":"Y0"}},{"name":"x1","in":"query","required":true,"schema":{"type":"number","title":"X1"}},{"name":"y1","in":"query","required":true,"schema":{"type":"number","title":"Y1"}},{"name":"w","in":"query","required":true,"schema":{"type":"integer","maximum":8192,"minimum":2,"title":"W"}},{"name":"h","in":"query","required":true,"schema":{"type":"integer","maximum":8192,"minimum":2,"title":"H"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/jobs/{job_id}/verify":{"post":{"summary":"Verify Job","description":"Re-measure trace width, spacing, hole sizes, annular ring and coverage on a high-res raster and\ncompare with the vector-derived specs. Cached per job.","operationId":"verify_job_api_v1_jobs__job_id__verify_post","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImageVerification"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/jobs/{job_id}/verify/{side}.png":{"get":{"summary":"Verify Overlay","operationId":"verify_overlay_api_v1_jobs__job_id__verify__side__png_get","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}},{"name":"side","in":"path","required":true,"schema":{"type":"string","title":"Side"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/jobs/{job_id}/label":{"post":{"summary":"Label Job","description":"Record what the fab actually decided for this board. This is the training signal for the local model.","operationId":"label_job_api_v1_jobs__job_id__label_post","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LabelRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Label Job Api V1 Jobs  Job Id  Label Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ml/status":{"get":{"summary":"Ml Status","operationId":"ml_status_api_v1_ml_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Ml Status Api V1 Ml Status Get"}}}}}}},"/api/v1/ml/train":{"post":{"summary":"Ml Train","description":"Retrain the local model from the dataset (plus synthetic bootstrap unless disabled). Hot-reloaded on next prediction.","operationId":"ml_train_api_v1_ml_train_post","parameters":[{"name":"synthetic","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":4000,"title":"Synthetic"}},{"name":"real_only","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Real Only"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TrainReport"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"AgentInfo":{"properties":{"name":{"type":"string","title":"Name"},"title":{"type":"string","title":"Title"},"version":{"type":"string","title":"Version"},"kind":{"type":"string","enum":["extractor","checker","inspector","generator","creator","reader"],"title":"Kind"},"description":{"type":"string","title":"Description"},"inputs":{"items":{"type":"string"},"type":"array","title":"Inputs","description":"what the sub-agent consumes"},"outputs":{"items":{"type":"string"},"type":"array","title":"Outputs","description":"what it produces"},"endpoints":{"items":{"type":"string"},"type":"array","title":"Endpoints","description":"API routes that expose it"},"trainable":{"type":"boolean","title":"Trainable","default":false},"model":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Model","description":"model / dataset status when trainable"},"params":{"additionalProperties":{"type":"string"},"type":"object","title":"Params","description":"run() parameters and their meaning"}},"type":"object","required":["name","title","version","kind","description"],"title":"AgentInfo"},"Alignment":{"properties":{"scale":{"type":"number","title":"Scale","default":1.0},"mirror_bottom":{"type":"boolean","title":"Mirror Bottom","default":true},"rotation_deg":{"type":"integer","title":"Rotation Deg","default":0},"dx_mm":{"type":"number","title":"Dx Mm","default":0.0},"dy_mm":{"type":"number","title":"Dy Mm","default":0.0},"matched":{"type":"integer","title":"Matched","default":0},"total":{"type":"integer","title":"Total","default":0},"score":{"type":"number","title":"Score","default":0.0},"unit_guess":{"type":"string","title":"Unit Guess","default":"mm"},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note"}},"type":"object","title":"Alignment","description":"How the pick-and-place coordinates were mapped onto the Gerber coordinates."},"AnalysisResult":{"properties":{"job_id":{"type":"string","title":"Job Id"},"board_name":{"type":"string","title":"Board Name"},"generator":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Generator","description":"EDA tool guessed from the files, e.g. 'kicad'"},"uploaded_files":{"items":{"type":"string"},"type":"array","title":"Uploaded Files"},"other_boards":{"items":{"type":"string"},"type":"array","title":"Other Boards","description":"Other designs found in the same upload (analyse with ?board=)"},"outline":{"$ref":"#/components/schemas/BoardOutline"},"layers":{"items":{"$ref":"#/components/schemas/LayerInfo"},"type":"array","title":"Layers"},"drills":{"$ref":"#/components/schemas/DrillSummary"},"metrics":{"$ref":"#/components/schemas/Metrics"},"pads":{"$ref":"#/components/schemas/PadSummary"},"mask":{"$ref":"#/components/schemas/MaskStats"},"construction":{"$ref":"#/components/schemas/FlexAssessment"},"units":{"$ref":"#/components/schemas/UnitsSummary"},"documents":{"items":{"$ref":"#/components/schemas/DocumentInfo"},"type":"array","title":"Documents","description":"Fab drawings, READMEs, sketches and drawing layers that were read for specs"},"fab_notes":{"items":{"type":"string"},"type":"array","title":"Fab Notes","description":"Numbered notes found verbatim in the documents"},"jobfile":{"anyOf":[{"$ref":"#/components/schemas/JobFile"},{"type":"null"}],"description":"Gerber Job File (*.gbrjob) when the package has one"},"drawing":{"anyOf":[{"$ref":"#/components/schemas/DrawingInfo"},{"type":"null"}],"description":"The richest fab drawing in the package, parsed (notes, drill/stackup/impedance tables)"},"spec_sheet":{"items":{"$ref":"#/components/schemas/SpecItem"},"type":"array","title":"Spec Sheet","description":"Quote-ready specs; defaults filled in where not measurable"},"quote_sheet":{"items":{"$ref":"#/components/schemas/QuoteRow"},"type":"array","title":"Quote Sheet","description":"The 65-row customer quote template, filled; download as /jobs/{id}/quote.xlsx"},"files":{"items":{"$ref":"#/components/schemas/FileRole"},"type":"array","title":"Files","description":"Every file in the upload and what it was taken for"},"stackup":{"items":{"$ref":"#/components/schemas/StackupLayer"},"type":"array","title":"Stackup","description":"Top to bottom, from the layers present"},"outline_polygon_mm":{"items":{"items":{"type":"number"},"type":"array"},"type":"array","title":"Outline Polygon Mm","description":"Board contour (x, y) in mm, for 2D/3D views"},"cutouts_mm":{"items":{"items":{"items":{"type":"number"},"type":"array"},"type":"array"},"type":"array","title":"Cutouts Mm"},"renders":{"$ref":"#/components/schemas/Renders"},"review":{"anyOf":[{"$ref":"#/components/schemas/PcbReview"},{"type":"null"}]},"review_meta":{"anyOf":[{"$ref":"#/components/schemas/ReviewMeta"},{"type":"null"}]},"review_error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Review Error","description":"Set when the optional LLM review was requested but failed"},"parser_warnings":{"items":{"type":"string"},"type":"array","title":"Parser Warnings"},"analysis_ms":{"type":"integer","title":"Analysis Ms"}},"type":"object","required":["job_id","board_name","uploaded_files","outline","layers","drills","metrics","renders","analysis_ms"],"title":"AnalysisResult"},"AnnularRingStats":{"properties":{"pads":{"type":"integer","title":"Pads","default":0},"min_mm":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Min Mm"},"p05_mm":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"P05 Mm","description":"5th percentile - robust 'typical minimum'"},"median_mm":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Median Mm"},"below_0_10":{"type":"integer","title":"Below 0 10","default":0},"below_0_125":{"type":"integer","title":"Below 0 125","default":0},"below_0_15":{"type":"integer","title":"Below 0 15","default":0},"smallest":{"items":{"$ref":"#/components/schemas/RingSample"},"type":"array","title":"Smallest","description":"The smallest rings, where they are"}},"type":"object","title":"AnnularRingStats","description":"Ring per drilled pad on the outer copper layers = copper left on the worst side, drill drift included:\n(R_pad - R_hole) - D_centres for round pads, min axis margin - R_hole for rectangular / oblong pads."},"ApertureStat":{"properties":{"code":{"type":"string","title":"Code","description":"D-code, e.g. 'D10'"},"shape":{"type":"string","title":"Shape"},"size_mm":{"items":{"type":"number"},"type":"array","title":"Size Mm","description":"circle: [d]; rect/obround: [w, h]; polygon: [d, n]"},"hole_mm":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Hole Mm"},"function":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Function","description":"Gerber X2 .AperFunction, if present"},"flashes":{"type":"integer","title":"Flashes","default":0},"strokes":{"type":"integer","title":"Strokes","default":0}},"type":"object","required":["code","shape","size_mm"],"title":"ApertureStat"},"AssemblyResult":{"properties":{"job_id":{"type":"string","title":"Job Id"},"board":{"$ref":"#/components/schemas/BoardInfo"},"pnp":{"anyOf":[{"$ref":"#/components/schemas/PnpFile"},{"type":"null"}]},"bom":{"anyOf":[{"$ref":"#/components/schemas/BomFile"},{"type":"null"}]},"footprints":{"items":{"$ref":"#/components/schemas/Footprint"},"type":"array","title":"Footprints"},"components":{"items":{"$ref":"#/components/schemas/Component"},"type":"array","title":"Components"},"alignment":{"anyOf":[{"$ref":"#/components/schemas/Alignment"},{"type":"null"}]},"findings":{"items":{"$ref":"#/components/schemas/DfaFinding"},"type":"array","title":"Findings"},"summary":{"$ref":"#/components/schemas/AssemblySummary"},"warnings":{"items":{"type":"string"},"type":"array","title":"Warnings"}},"type":"object","required":["job_id","board"],"title":"AssemblyResult"},"AssemblySummary":{"properties":{"placements":{"type":"integer","title":"Placements","default":0},"smt_top":{"type":"integer","title":"Smt Top","default":0},"smt_bottom":{"type":"integer","title":"Smt Bottom","default":0},"through_hole":{"type":"integer","title":"Through Hole","default":0},"bga":{"type":"integer","title":"Bga","default":0},"fine_pitch":{"type":"integer","title":"Fine Pitch","default":0},"dnp":{"type":"integer","title":"Dnp","default":0},"unique_parts":{"type":"integer","title":"Unique Parts","default":0},"bom_lines":{"type":"integer","title":"Bom Lines","default":0},"sides":{"type":"integer","title":"Sides","default":0},"unmatched_bom_refs":{"type":"integer","title":"Unmatched Bom Refs","default":0},"unmatched_placements":{"type":"integer","title":"Unmatched Placements","default":0},"pads_without_component":{"type":"integer","title":"Pads Without Component","default":0},"critical":{"type":"integer","title":"Critical","default":0},"warnings":{"type":"integer","title":"Warnings","default":0}},"type":"object","title":"AssemblySummary"},"BoardInfo":{"properties":{"name":{"type":"string","title":"Name"},"width_mm":{"type":"number","title":"Width Mm"},"height_mm":{"type":"number","title":"Height Mm"},"bounds_mm":{"prefixItems":[{"prefixItems":[{"type":"number"},{"type":"number"}],"type":"array","maxItems":2,"minItems":2},{"prefixItems":[{"type":"number"},{"type":"number"}],"type":"array","maxItems":2,"minItems":2}],"type":"array","maxItems":2,"minItems":2,"title":"Bounds Mm"},"outline_polygon_mm":{"items":{"prefixItems":[{"type":"number"},{"type":"number"}],"type":"array","maxItems":2,"minItems":2},"type":"array","title":"Outline Polygon Mm"},"copper_layers":{"type":"integer","title":"Copper Layers","default":0},"has_top_paste":{"type":"boolean","title":"Has Top Paste","default":false},"has_bottom_paste":{"type":"boolean","title":"Has Bottom Paste","default":false},"renders":{"items":{"type":"string"},"type":"array","title":"Renders","description":"layer keys the view endpoint can draw"}},"type":"object","required":["name","width_mm","height_mm","bounds_mm"],"title":"BoardInfo"},"BoardOutline":{"properties":{"has_outline_layer":{"type":"boolean","title":"Has Outline Layer"},"width":{"$ref":"#/components/schemas/Dimension"},"height":{"$ref":"#/components/schemas/Dimension"},"area_mm2":{"type":"number","title":"Area Mm2","description":"Bounding-box area"},"bounds_mm":{"prefixItems":[{"prefixItems":[{"type":"number"},{"type":"number"}],"type":"array","maxItems":2,"minItems":2},{"prefixItems":[{"type":"number"},{"type":"number"}],"type":"array","maxItems":2,"minItems":2}],"type":"array","maxItems":2,"minItems":2,"title":"Bounds Mm","description":"((min_x, min_y), (max_x, max_y)) in mm"},"shape":{"type":"string","enum":["rectangle","rounded_rectangle","circle","complex","unknown"],"title":"Shape","default":"unknown"},"polygon_area_mm2":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Polygon Area Mm2","description":"True board area inside the outline contour"},"perimeter_mm":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Perimeter Mm"},"corner_radius_mm":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Corner Radius Mm"},"contour_count":{"type":"integer","title":"Contour Count","default":0},"cutout_count":{"type":"integer","title":"Cutout Count","description":"Closed contours inside the board outline (internal routing)","default":0},"outline_closed":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Outline Closed","description":"False when the outline has gaps"}},"type":"object","required":["has_outline_layer","width","height","area_mm2","bounds_mm"],"title":"BoardOutline"},"BoardRegion":{"properties":{"id":{"type":"string","title":"Id","description":"R1.. rigid, F1.. flex"},"type":{"type":"string","enum":["rigid","flex"],"title":"Type"},"polygon_mm":{"items":{"prefixItems":[{"type":"number"},{"type":"number"}],"type":"array","maxItems":2,"minItems":2},"type":"array","title":"Polygon Mm"},"bbox_mm":{"prefixItems":[{"prefixItems":[{"type":"number"},{"type":"number"}],"type":"array","maxItems":2,"minItems":2},{"prefixItems":[{"type":"number"},{"type":"number"}],"type":"array","maxItems":2,"minItems":2}],"type":"array","maxItems":2,"minItems":2,"title":"Bbox Mm"},"area_mm2":{"type":"number","title":"Area Mm2"},"copper_layers":{"items":{"type":"string"},"type":"array","title":"Copper Layers","description":"Copper layer keys that carry copper inside the region"},"coverlay":{"type":"boolean","title":"Coverlay","default":false},"bend_area":{"type":"boolean","title":"Bend Area","default":false},"stiffener":{"type":"boolean","title":"Stiffener","default":false},"confidence":{"type":"integer","title":"Confidence","description":"0-100; flex regions only","default":0},"evidence":{"items":{"type":"string"},"type":"array","title":"Evidence","description":"Rule ids that support this region"}},"type":"object","required":["id","type","polygon_mm","bbox_mm","area_mm2"],"title":"BoardRegion","description":"A rigid or flex section of the outline: what the DFM engine applies region-specific rules to."},"Body_add_assembly_files_api_v1_jobs__job_id__assembly_files_post":{"properties":{"files":{"items":{"type":"string","contentMediaType":"application/octet-stream"},"type":"array","title":"Files","description":"pick-and-place and/or BOM to attach or replace"}},"type":"object","required":["files"],"title":"Body_add_assembly_files_api_v1_jobs__job_id__assembly_files_post"},"Body_add_job_files_api_v1_jobs__job_id__files_post":{"properties":{"files":{"items":{"type":"string","contentMediaType":"application/octet-stream"},"type":"array","title":"Files","description":"Additional files: drill, stackup, fab drawing PDF, mechanical layers, README..."}},"type":"object","required":["files"],"title":"Body_add_job_files_api_v1_jobs__job_id__files_post"},"Body_analyze_api_v1_analyze_post":{"properties":{"files":{"items":{"type":"string","contentMediaType":"application/octet-stream"},"type":"array","title":"Files","description":"Gerber/Excellon files and/or .zip archives"}},"type":"object","required":["files"],"title":"Body_analyze_api_v1_analyze_post"},"Body_analyze_assembly_api_v1_assembly_post":{"properties":{"files":{"items":{"type":"string","contentMediaType":"application/octet-stream"},"type":"array","title":"Files","description":"Gerber package plus the pick-and-place (centroid) file and the BOM"}},"type":"object","required":["files"],"title":"Body_analyze_assembly_api_v1_assembly_post"},"Body_bom_validate_api_v1_bom_validate_post":{"properties":{"file":{"type":"string","contentMediaType":"application/octet-stream","title":"File","description":"BOM CSV / TSV / XLSX"}},"type":"object","required":["file"],"title":"Body_bom_validate_api_v1_bom_validate_post"},"Body_pnp_parse_api_v1_pnp_parse_post":{"properties":{"file":{"type":"string","contentMediaType":"application/octet-stream","title":"File","description":"pick-and-place / centroid file"}},"type":"object","required":["file"],"title":"Body_pnp_parse_api_v1_pnp_parse_post"},"BomFile":{"properties":{"file":{"type":"string","title":"File"},"format":{"type":"string","title":"Format","default":"csv"},"columns":{"additionalProperties":{"type":"string"},"type":"object","title":"Columns"},"lines":{"items":{"$ref":"#/components/schemas/BomLine"},"type":"array","title":"Lines"},"warnings":{"items":{"type":"string"},"type":"array","title":"Warnings"}},"type":"object","required":["file"],"title":"BomFile"},"BomLine":{"properties":{"row":{"type":"integer","title":"Row"},"refs":{"items":{"type":"string"},"type":"array","title":"Refs"},"qty":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Qty"},"value":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Value"},"package":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Package"},"mpn":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Mpn"},"manufacturer":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Manufacturer"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"dnp":{"type":"boolean","title":"Dnp","default":false}},"type":"object","required":["row"],"title":"BomLine"},"Component":{"properties":{"ref":{"type":"string","title":"Ref"},"side":{"type":"string","enum":["top","bottom"],"title":"Side"},"x_mm":{"type":"number","title":"X Mm"},"y_mm":{"type":"number","title":"Y Mm"},"rotation":{"type":"number","title":"Rotation","default":0.0},"value":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Value"},"package":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Package"},"mpn":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Mpn"},"bom_row":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Bom Row"},"bom_package":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Bom Package"},"footprint":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Footprint"},"kind":{"type":"string","enum":["smd","th","bga","unknown"],"title":"Kind","default":"unknown"},"dnp":{"type":"boolean","title":"Dnp","default":false},"status":{"items":{"type":"string"},"type":"array","title":"Status","description":"short flags: ok, no-bom, no-pads, off-board, ..."}},"type":"object","required":["ref","side","x_mm","y_mm"],"title":"Component"},"DfaFinding":{"properties":{"rule":{"type":"string","title":"Rule"},"severity":{"type":"string","enum":["critical","warning","info"],"title":"Severity"},"title":{"type":"string","title":"Title"},"detail":{"type":"string","title":"Detail"},"refs":{"items":{"type":"string"},"type":"array","title":"Refs"},"at_mm":{"anyOf":[{"prefixItems":[{"type":"number"},{"type":"number"}],"type":"array","maxItems":2,"minItems":2},{"type":"null"}],"title":"At Mm"},"side":{"anyOf":[{"type":"string","enum":["top","bottom"]},{"type":"null"}],"title":"Side"}},"type":"object","required":["rule","severity","title","detail"],"title":"DfaFinding"},"DfmFinding":{"properties":{"severity":{"type":"string","enum":["info","warning","critical"],"title":"Severity"},"title":{"type":"string","title":"Title"},"detail":{"type":"string","title":"Detail"},"layer":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Layer"}},"type":"object","required":["severity","title","detail"],"title":"DfmFinding"},"Dimension":{"properties":{"mm":{"type":"number","title":"Mm"},"inch":{"type":"number","title":"Inch"}},"type":"object","required":["mm","inch"],"title":"Dimension"},"DocRef":{"properties":{"file":{"type":"string","title":"File"},"page":{"type":"integer","title":"Page"},"bbox":{"prefixItems":[{"type":"number"},{"type":"number"},{"type":"number"},{"type":"number"}],"type":"array","maxItems":4,"minItems":4,"title":"Bbox","description":"x0, y0, x1, y1 as fractions of the page (0..1), origin top-left"}},"type":"object","required":["file","page","bbox"],"title":"DocRef","description":"Where a value was read in a document: page number and a box on that page (fractions of page width/height)."},"DocSpecFound":{"properties":{"key":{"type":"string","title":"Key"},"label":{"type":"string","title":"Label"},"value":{"type":"string","title":"Value"},"snippet":{"type":"string","title":"Snippet","description":"The text around the match, as evidence","default":""},"ref":{"anyOf":[{"$ref":"#/components/schemas/DocRef"},{"type":"null"}],"description":"Page and box where it was read"}},"type":"object","required":["key","label","value"],"title":"DocSpecFound"},"DocumentInfo":{"properties":{"file":{"type":"string","title":"File"},"kind":{"type":"string","enum":["pdf","image","text","drawing-layer","jobfile"],"title":"Kind"},"chars":{"type":"integer","title":"Chars","default":0},"specs_found":{"type":"integer","title":"Specs Found","default":0},"notes_found":{"type":"integer","title":"Notes Found","default":0},"ocr":{"type":"boolean","title":"Ocr","default":false},"pages":{"type":"integer","title":"Pages","description":"Page count (PDF) / 1 for an image; pages render at /jobs/{id}/documents/{file}/pages/{n}.png","default":0},"preview":{"type":"string","title":"Preview","default":""},"specs":{"items":{"$ref":"#/components/schemas/DocSpecFound"},"type":"array","title":"Specs","description":"What this document contributed"},"text":{"type":"string","title":"Text","description":"Extracted / OCR'd text (first 20k chars)","default":""},"drawing":{"anyOf":[{"$ref":"#/components/schemas/DrawingInfo"},{"type":"null"}],"description":"Structured content of a fab drawing (notes, tables, title block)"}},"type":"object","required":["file","kind"],"title":"DocumentInfo"},"DrawingArray":{"properties":{"part_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Part Name"},"part_size_mm":{"anyOf":[{"prefixItems":[{"type":"number"},{"type":"number"}],"type":"array","maxItems":2,"minItems":2},{"type":"null"}],"title":"Part Size Mm"},"array_size_mm":{"anyOf":[{"prefixItems":[{"type":"number"},{"type":"number"}],"type":"array","maxItems":2,"minItems":2},{"type":"null"}],"title":"Array Size Mm"},"boards":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Boards"},"matrix":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Matrix"},"spacing_mm":{"anyOf":[{"prefixItems":[{"type":"number"},{"type":"number"}],"type":"array","maxItems":2,"minItems":2},{"type":"null"}],"title":"Spacing Mm"},"ref":{"anyOf":[{"$ref":"#/components/schemas/DocRef"},{"type":"null"}]}},"type":"object","title":"DrawingArray"},"DrawingDrill":{"properties":{"symbol":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Symbol"},"size_mm":{"type":"number","title":"Size Mm"},"tolerance":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tolerance"},"plated":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Plated"},"count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Count"},"span":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Span","description":"'L1-L4' when the table is per drill span"},"page":{"type":"integer","title":"Page","default":0},"text":{"type":"string","title":"Text","description":"The row as printed","default":""},"ref":{"anyOf":[{"$ref":"#/components/schemas/DocRef"},{"type":"null"}]}},"type":"object","required":["size_mm"],"title":"DrawingDrill"},"DrawingImpedance":{"properties":{"ohms":{"type":"integer","title":"Ohms"},"kind":{"type":"string","enum":["se","diff"],"title":"Kind","default":"se"},"tolerance":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tolerance"},"layers":{"items":{"type":"integer"},"type":"array","title":"Layers"},"trace_mm":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Trace Mm"},"space_mm":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Space Mm"},"ref":{"anyOf":[{"$ref":"#/components/schemas/DocRef"},{"type":"null"}]}},"type":"object","required":["ohms"],"title":"DrawingImpedance"},"DrawingInfo":{"properties":{"file":{"type":"string","title":"File"},"notes":{"items":{"type":"string"},"type":"array","title":"Notes"},"notes_refs":{"items":{"anyOf":[{"$ref":"#/components/schemas/DocRef"},{"type":"null"}]},"type":"array","title":"Notes Refs","description":"Where each note sits on the page, parallel to `notes`"},"title_refs":{"additionalProperties":{"$ref":"#/components/schemas/DocRef"},"type":"object","title":"Title Refs"},"drill_table":{"items":{"$ref":"#/components/schemas/DrawingDrill"},"type":"array","title":"Drill Table"},"stackup":{"items":{"$ref":"#/components/schemas/DrawingStack"},"type":"array","title":"Stackup"},"stackup_page":{"type":"integer","title":"Stackup Page","default":0},"impedance":{"items":{"$ref":"#/components/schemas/DrawingImpedance"},"type":"array","title":"Impedance"},"title":{"additionalProperties":{"type":"string"},"type":"object","title":"Title","description":"document_no, rev, title, date, drawn, size"},"array":{"anyOf":[{"$ref":"#/components/schemas/DrawingArray"},{"type":"null"}]},"layer_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Layer Count"},"thickness_mm":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Thickness Mm"},"thickness_tolerance":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Thickness Tolerance"}},"type":"object","required":["file"],"title":"DrawingInfo","description":"What a fab drawing / sketch PDF says, as structure: notes, drill table, stackup, impedance, title block."},"DrawingStack":{"properties":{"kind":{"type":"string","enum":["copper","dielectric","mask","silk","paste"],"title":"Kind"},"layer":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Layer"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Type","description":"signal / plane / mixed for copper rows"},"copper_oz":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Copper Oz"},"thickness_mm":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Thickness Mm"},"material":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Material"},"text":{"type":"string","title":"Text","default":""},"ref":{"anyOf":[{"$ref":"#/components/schemas/DocRef"},{"type":"null"}]}},"type":"object","required":["kind"],"title":"DrawingStack"},"DrillSize":{"properties":{"diameter_mm":{"type":"number","title":"Diameter Mm"},"count":{"type":"integer","title":"Count"},"plated":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Plated","description":"True=PTH, False=NPTH, None=unknown"},"function":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Function","description":"X2 .AperFunction of the tool: ViaDrill, ComponentDrill, MechanicalDrill, CastellatedDrill, Slot ..."},"tolerance_mm":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tolerance Mm","description":"X2 .DrillTolerance as '+0.05/-0.03'"}},"type":"object","required":["diameter_mm","count"],"title":"DrillSize"},"DrillSpan":{"properties":{"file":{"type":"string","title":"File"},"from_layer":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"From Layer"},"to_layer":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"To Layer"},"kind":{"type":"string","enum":["through","blind","buried","unknown"],"title":"Kind"},"plated":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Plated"},"layer_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Layer Key","description":"Render/layer key of this drill file, e.g. 'drill pth_1'"},"label":{"type":"string","title":"Label","description":"'L1-L2', 'L1-L8 (through)', ...","default":""},"source":{"type":"string","enum":["x2","name","odb","ldp","geometry","none"],"title":"Source","default":"none"},"from_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"From Key","description":"Copper layer key at the start of the span, e.g. 'top copper'"},"to_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"To Key"},"hole_count":{"type":"integer","title":"Hole Count","default":0},"min_hole_mm":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Min Hole Mm"},"max_hole_mm":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Max Hole Mm"},"at":{"anyOf":[{"prefixItems":[{"type":"number"},{"type":"number"}],"type":"array","maxItems":2,"minItems":2},{"type":"null"}],"title":"At","description":"A hole of this span (the smallest) to locate on the board"},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note"}},"type":"object","required":["file","from_layer","to_layer","kind","plated"],"title":"DrillSpan","description":"One drill file and the copper layers it connects. `kind` comes from the X2 header, the file/ODB name, or\n(source='geometry') from which copper layers carry a pad at the holes."},"DrillSummary":{"properties":{"files":{"items":{"type":"string"},"type":"array","title":"Files"},"spans":{"items":{"$ref":"#/components/schemas/DrillSpan"},"type":"array","title":"Spans"},"via_count":{"type":"integer","title":"Via Count","default":0},"component_hole_count":{"type":"integer","title":"Component Hole Count","default":0},"holes_without_pad":{"type":"integer","title":"Holes Without Pad","default":0},"classification_source":{"type":"string","enum":["x2_attributes","geometry","none"],"title":"Classification Source","default":"none"},"total_holes":{"type":"integer","title":"Total Holes"},"plated_holes":{"type":"integer","title":"Plated Holes"},"non_plated_holes":{"type":"integer","title":"Non Plated Holes"},"unknown_plating_holes":{"type":"integer","title":"Unknown Plating Holes"},"slot_count":{"type":"integer","title":"Slot Count"},"min_hole_mm":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Min Hole Mm"},"max_hole_mm":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Max Hole Mm"},"min_hole_at":{"anyOf":[{"prefixItems":[{"type":"number"},{"type":"number"}],"type":"array","maxItems":2,"minItems":2},{"type":"null"}],"title":"Min Hole At"},"max_hole_at":{"anyOf":[{"prefixItems":[{"type":"number"},{"type":"number"}],"type":"array","maxItems":2,"minItems":2},{"type":"null"}],"title":"Max Hole At"},"sizes":{"items":{"$ref":"#/components/schemas/DrillSize"},"type":"array","title":"Sizes"}},"type":"object","required":["files","total_holes","plated_holes","non_plated_holes","unknown_plating_holes","slot_count","min_hole_mm","max_hole_mm","sizes"],"title":"DrillSummary"},"FileMeta":{"properties":{"format":{"type":"string","enum":["gerber","excellon","ipc356","odb++","unknown"],"title":"Format"},"units":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Units","description":"'mm' or 'inch'"},"number_format":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Number Format","description":"integer.decimal digits, e.g. '4.5'"},"zero_suppression":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Zero Suppression"},"generation_software":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Generation Software"},"creation_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Creation Date"},"file_function":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"File Function"},"file_polarity":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"File Polarity"},"is_x2":{"type":"boolean","title":"Is X2","default":false},"attributes":{"additionalProperties":{"type":"string"},"type":"object","title":"Attributes","description":"All Gerber X2 %TF file attributes"}},"type":"object","required":["format"],"title":"FileMeta"},"FileRole":{"properties":{"filename":{"type":"string","title":"Filename"},"status":{"type":"string","enum":["used","empty","other","ignored","skipped"],"title":"Status"},"role":{"type":"string","title":"Role","description":"'top copper', 'bottom soldermask', 'assembly drawing', 'not CAM data', ...; 'empty' = recognised layer file with no drawn objects"},"layer_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Layer Key"},"format":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Format"},"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reason"}},"type":"object","required":["filename","status","role"],"title":"FileRole"},"FileUnits":{"properties":{"file":{"type":"string","title":"File"},"layer_key":{"type":"string","title":"Layer Key"},"format":{"type":"string","title":"Format","description":"gerber / excellon / odb++"},"unit":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Unit","description":"'mm' or 'inch' as declared in the file header"},"number_format":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Number Format","description":"integer.decimal digits, e.g. '4.5' (Gerber %FS) or '2.4' (Excellon)"},"resolution_um":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Resolution Um","description":"Smallest coordinate step, in micrometres"},"normalised":{"type":"string","title":"Normalised","description":"All geometry is converted to this unit for analysis","default":"mm"},"scale_to_mm":{"type":"number","title":"Scale To Mm","default":1.0},"status":{"type":"string","enum":["ok","low_resolution","unit_missing","misaligned"],"title":"Status","default":"ok"},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note"}},"type":"object","required":["file","layer_key","format"],"title":"FileUnits"},"FlexAssessment":{"properties":{"board_type":{"type":"string","enum":["rigid","flex","rigid-flex"],"title":"Board Type","default":"rigid"},"classification":{"type":"string","enum":["rigid","possible_flex","flex"],"title":"Classification","description":"Score class: flex (confident), possible_flex (review), rigid","default":"rigid"},"confidence":{"type":"number","title":"Confidence","default":0.0},"score":{"type":"integer","title":"Score","description":"Sum of the fired rules' weights","default":0},"rules":{"items":{"$ref":"#/components/schemas/FlexEvidence"},"type":"array","title":"Rules"},"regions":{"items":{"$ref":"#/components/schemas/BoardRegion"},"type":"array","title":"Regions","description":"Rigid / flex sections with their copper layers"},"review_warning":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Review Warning","description":"Set when the evidence is suggestive but not conclusive"},"evidence":{"items":{"type":"string"},"type":"array","title":"Evidence"},"hatched_copper":{"type":"boolean","title":"Hatched Copper","default":false},"hatch_pitch_mm":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Hatch Pitch Mm"},"hatch_line_width_mm":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Hatch Line Width Mm"},"neck_ratio":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Neck Ratio","description":"Narrowest section / widest section of the outline"},"flex_regions_mm":{"items":{"prefixItems":[{"prefixItems":[{"type":"number"},{"type":"number"}],"type":"array","maxItems":2,"minItems":2},{"prefixItems":[{"type":"number"},{"type":"number"}],"type":"array","maxItems":2,"minItems":2}],"type":"array","maxItems":2,"minItems":2},"type":"array","title":"Flex Regions Mm","description":"Flex sections as bboxes (bend axes for the 3D view)"},"flex_polygons_mm":{"items":{"items":{"prefixItems":[{"type":"number"},{"type":"number"}],"type":"array","maxItems":2,"minItems":2},"type":"array"},"type":"array","title":"Flex Polygons Mm","description":"Flex sections as polygons: the outline area where the rigid-only layers (outer copper, mask, silk) do not exist"},"flex_area_pct":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Flex Area Pct","description":"Share of the board area that is flex"},"coverlay_layers":{"items":{"type":"string"},"type":"array","title":"Coverlay Layers"},"stiffener_layers":{"items":{"type":"string"},"type":"array","title":"Stiffener Layers"},"bend_line_layers":{"items":{"type":"string"},"type":"array","title":"Bend Line Layers"},"flex_copper_layers":{"items":{"type":"string"},"type":"array","title":"Flex Copper Layers","description":"Copper layers that run through the flex section"},"rigid_only_copper_layers":{"items":{"type":"string"},"type":"array","title":"Rigid Only Copper Layers","description":"Copper layers whose copper stops at the rigid areas"},"layer_notes":{"items":{"type":"string"},"type":"array","title":"Layer Notes","description":"How the rigid/flex layer split was decided"}},"type":"object","title":"FlexAssessment"},"FlexEvidence":{"properties":{"rule":{"type":"string","title":"Rule","description":"F01 fab-drawing label, F02 regional stack-up, F03 coverlay, F04 polyimide core, F05 copper termination, F06 separate stack-ups, F07 bend info, F08 adhesive, F09 stiffener, F10 neck, F11 file names, F13 hatched copper"},"strength":{"type":"string","enum":["very_high","high","medium_high","medium","supporting","weak"],"title":"Strength"},"score":{"type":"integer","title":"Score"},"text":{"type":"string","title":"Text"},"source":{"type":"string","title":"Source","description":"File / document / 'geometry'","default":""}},"type":"object","required":["rule","strength","score","text"],"title":"FlexEvidence","description":"One flex-detection rule that fired (F01..F13), with its weight."},"Footprint":{"properties":{"id":{"type":"string","title":"Id"},"side":{"type":"string","enum":["top","bottom"],"title":"Side"},"cx":{"type":"number","title":"Cx"},"cy":{"type":"number","title":"Cy"},"bbox":{"prefixItems":[{"prefixItems":[{"type":"number"},{"type":"number"}],"type":"array","maxItems":2,"minItems":2},{"prefixItems":[{"type":"number"},{"type":"number"}],"type":"array","maxItems":2,"minItems":2}],"type":"array","maxItems":2,"minItems":2,"title":"Bbox"},"pad_count":{"type":"integer","title":"Pad Count"},"pitch_mm":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Pitch Mm"},"min_pad_mm":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Min Pad Mm"},"kind":{"type":"string","enum":["smd","th","bga"],"title":"Kind","default":"smd"},"pads":{"items":{"prefixItems":[{"type":"number"},{"type":"number"},{"type":"number"},{"type":"number"}],"type":"array","maxItems":4,"minItems":4},"type":"array","title":"Pads","description":"(cx, cy, w, h) of each pad, mm"}},"type":"object","required":["id","side","cx","cy","bbox","pad_count"],"title":"Footprint","description":"A group of pads on one side of the board that belongs to one component."},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"HoleSizeCheck":{"properties":{"tool_diameter_mm":{"type":"number","title":"Tool Diameter Mm"},"holes":{"type":"integer","title":"Holes"},"measured_mean_mm":{"type":"number","title":"Measured Mean Mm"},"max_deviation_mm":{"type":"number","title":"Max Deviation Mm"},"tolerance_mm":{"type":"number","title":"Tolerance Mm"},"status":{"type":"string","enum":["agree","mismatch"],"title":"Status"}},"type":"object","required":["tool_diameter_mm","holes","measured_mean_mm","max_deviation_mm","tolerance_mm","status"],"title":"HoleSizeCheck"},"ImageVerification":{"properties":{"resolution_um_per_px":{"type":"number","title":"Resolution Um Per Px"},"image_size_px":{"items":{"type":"integer"},"type":"array","title":"Image Size Px"},"checks":{"items":{"$ref":"#/components/schemas/VerificationCheck"},"type":"array","title":"Checks"},"hole_sizes":{"items":{"$ref":"#/components/schemas/HoleSizeCheck"},"type":"array","title":"Hole Sizes"},"min_copper_width_mm":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Min Copper Width Mm","description":"Narrowest copper feature as built (traces, pour necks, thermals)"},"min_spacing_mm":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Min Spacing Mm","description":"Narrowest copper-to-copper gap (image only)"},"min_spacing_by_side":{"additionalProperties":{"type":"number"},"type":"object","title":"Min Spacing By Side"},"overlays":{"items":{"type":"string"},"type":"array","title":"Overlays","description":"sides with a PNG at /jobs/{id}/verify/{side}.png"},"status":{"type":"string","enum":["agree","narrower","mismatch","n/a"],"title":"Status"},"duration_ms":{"type":"integer","title":"Duration Ms"}},"type":"object","required":["resolution_um_per_px","image_size_px","checks","hole_sizes","status","duration_ms"],"title":"ImageVerification"},"JobFile":{"properties":{"file":{"type":"string","title":"File"},"generation_software":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Generation Software"},"creation_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Creation Date"},"project_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Project Name"},"project_revision":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Project Revision"},"project_guid":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Project Guid"},"size_x_mm":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Size X Mm"},"size_y_mm":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Size Y Mm"},"layer_number":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Layer Number"},"board_thickness_mm":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Board Thickness Mm"},"finish":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Finish"},"impedance_controlled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Impedance Controlled"},"castellated":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Castellated"},"edge_plating":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Edge Plating"},"edge_connector":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Edge Connector"},"stackup":{"items":{"$ref":"#/components/schemas/JobFileLayer"},"type":"array","title":"Stackup"},"design_rules":{"items":{"$ref":"#/components/schemas/JobFileDesignRule"},"type":"array","title":"Design Rules"},"files":{"additionalProperties":{"type":"string"},"type":"object","title":"Files","description":"Path -> FileFunction as declared by the job file"}},"type":"object","required":["file"],"title":"JobFile","description":"Ucamco Gerber Job File (*.gbrjob): the CAD tool's own stackup / thickness / size / design rules."},"JobFileDesignRule":{"properties":{"layers":{"type":"string","title":"Layers"},"min_line_width_mm":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Min Line Width Mm"},"track_to_track_mm":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Track To Track Mm"},"pad_to_pad_mm":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Pad To Pad Mm"},"pad_to_track_mm":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Pad To Track Mm"},"track_to_region_mm":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Track To Region Mm"},"region_to_region_mm":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Region To Region Mm"}},"type":"object","required":["layers"],"title":"JobFileDesignRule"},"JobFileLayer":{"properties":{"position":{"type":"integer","title":"Position"},"type":{"type":"string","title":"Type","description":"Copper / Dielectric / SolderMask / Legend / SolderPaste ..."},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"thickness_mm":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Thickness Mm"},"material":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Material"},"color":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Color"},"notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes"},"dielectric_constant":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Dielectric Constant"}},"type":"object","required":["position","type"],"title":"JobFileLayer"},"JobSummary":{"properties":{"job_id":{"type":"string","title":"Job Id"},"board_name":{"type":"string","title":"Board Name"},"created_at":{"type":"number","title":"Created At"}},"type":"object","required":["job_id","board_name","created_at"],"title":"JobSummary"},"LabelRequest":{"properties":{"board_class":{"anyOf":[{"type":"string","enum":["standard","advanced","hdi"]},{"type":"null"}],"title":"Board Class"},"complexity_score":{"anyOf":[{"type":"number","maximum":10.0,"minimum":1.0},{"type":"null"}],"title":"Complexity Score"},"quoted_price":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Quoted Price","description":"Optional: unit price that was quoted"},"notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes"}},"type":"object","title":"LabelRequest","description":"Ground truth recorded after the fact (what the fab actually decided) - this is the ML training signal."},"LayerInfo":{"properties":{"key":{"type":"string","title":"Key","description":"Stable id, e.g. 'top copper', 'inner_01 copper', 'drill pth'"},"side":{"type":"string","title":"Side"},"use":{"type":"string","title":"Use"},"filename":{"type":"string","title":"Filename"},"object_count":{"type":"integer","title":"Object Count"},"aperture_count":{"type":"integer","title":"Aperture Count","default":0},"min_feature_mm":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Min Feature Mm","description":"Smallest drawn aperture width on this layer"},"bounds_mm":{"anyOf":[{"prefixItems":[{"prefixItems":[{"type":"number"},{"type":"number"}],"type":"array","maxItems":2,"minItems":2},{"prefixItems":[{"type":"number"},{"type":"number"}],"type":"array","maxItems":2,"minItems":2}],"type":"array","maxItems":2,"minItems":2},{"type":"null"}],"title":"Bounds Mm"},"meta":{"anyOf":[{"$ref":"#/components/schemas/FileMeta"},{"type":"null"}]},"flash_count":{"type":"integer","title":"Flash Count","default":0},"stroke_count":{"type":"integer","title":"Stroke Count","default":0},"region_count":{"type":"integer","title":"Region Count","default":0},"clear_polarity_objects":{"type":"integer","title":"Clear Polarity Objects","default":0},"off_board_objects":{"type":"integer","title":"Off Board Objects","description":"Objects outside the board outline (layer names, title blocks); ignored for specs","default":0},"hairline_strokes":{"type":"integer","title":"Hairline Strokes","description":"Strokes thinner than 0.025 mm (drawing/text artefacts, ignored for min trace)","default":0},"text_strokes":{"type":"integer","title":"Text Strokes","description":"Strokes recognised as copper text / nomenclature (glyph-sized groups touching no pad or pour); ignored for min trace and spacing","default":0},"min_trace_mm":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Min Trace Mm","description":"Smallest stroked (drawn) aperture >= 0.025 mm"},"min_flash_mm":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Min Flash Mm","description":"Smallest flashed (pad) aperture dimension"},"coverage_pct":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Coverage Pct","description":"Copper layers: % of board area covered"},"pour_count":{"type":"integer","title":"Pour Count","description":"Copper layers: solid polygon pours (regions)","default":0},"pour_area_mm2":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Pour Area Mm2","description":"Total area of solid pours"},"pour_coverage_pct":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Pour Coverage Pct","description":"Pour area / board area"},"largest_pour_bbox_mm":{"anyOf":[{"prefixItems":[{"prefixItems":[{"type":"number"},{"type":"number"}],"type":"array","maxItems":2,"minItems":2},{"prefixItems":[{"type":"number"},{"type":"number"}],"type":"array","maxItems":2,"minItems":2}],"type":"array","maxItems":2,"minItems":2},{"type":"null"}],"title":"Largest Pour Bbox Mm"},"hatched":{"type":"boolean","title":"Hatched","description":"Copper layers: contains a cross-hatched pour","default":false},"min_spacing_mm":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Min Spacing Mm","description":"Copper layers: narrowest copper-to-copper gap (raster measured)"},"min_spacing_at_mm":{"anyOf":[{"prefixItems":[{"type":"number"},{"type":"number"}],"type":"array","maxItems":2,"minItems":2},{"type":"null"}],"title":"Min Spacing At Mm"},"min_spacing_segment_mm":{"anyOf":[{"prefixItems":[{"prefixItems":[{"type":"number"},{"type":"number"}],"type":"array","maxItems":2,"minItems":2},{"prefixItems":[{"type":"number"},{"type":"number"}],"type":"array","maxItems":2,"minItems":2}],"type":"array","maxItems":2,"minItems":2},{"type":"null"}],"title":"Min Spacing Segment Mm","description":"Copper edge to copper edge across the narrowest gap"},"min_trace_segment_mm":{"anyOf":[{"prefixItems":[{"prefixItems":[{"type":"number"},{"type":"number"}],"type":"array","maxItems":2,"minItems":2},{"prefixItems":[{"type":"number"},{"type":"number"}],"type":"array","maxItems":2,"minItems":2}],"type":"array","maxItems":2,"minItems":2},{"type":"null"}],"title":"Min Trace Segment Mm","description":"Across the narrowest trace at its midpoint"},"section":{"type":"string","enum":["rigid+flex","rigid-only","flex-only","n/a"],"title":"Section","description":"Rigid-flex: where this layer's copper lives","default":"n/a"},"apertures":{"items":{"$ref":"#/components/schemas/ApertureStat"},"type":"array","title":"Apertures"}},"type":"object","required":["key","side","use","filename","object_count"],"title":"LayerInfo"},"MaskStats":{"properties":{"openings_top":{"type":"integer","title":"Openings Top","default":0},"openings_bottom":{"type":"integer","title":"Openings Bottom","default":0},"expansion_mm":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Expansion Mm","description":"Median (mask opening - copper pad) / 2 on matched pads"}},"type":"object","title":"MaskStats"},"Metrics":{"properties":{"copper_layer_count":{"type":"integer","title":"Copper Layer Count"},"inner_layer_count":{"type":"integer","title":"Inner Layer Count"},"stackup":{"items":{"type":"string"},"type":"array","title":"Stackup","description":"Copper layer keys, top to bottom"},"copper_coverage_pct_top":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Copper Coverage Pct Top"},"copper_coverage_pct_bottom":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Copper Coverage Pct Bottom"},"min_spacing_mm":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Min Spacing Mm","description":"Narrowest copper gap on the outer layers (raster measured)"},"min_spacing_mil":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Min Spacing Mil"},"pour_count":{"type":"integer","title":"Pour Count","description":"Solid copper pours on all copper layers","default":0},"has_hatched_copper":{"type":"boolean","title":"Has Hatched Copper","default":false},"min_trace_width_mm":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Min Trace Width Mm","description":"Smallest stroked aperture on any copper layer"},"min_trace_width_mil":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Min Trace Width Mil"},"min_trace_at":{"anyOf":[{"prefixItems":[{"type":"number"},{"type":"number"}],"type":"array","maxItems":2,"minItems":2},{"type":"null"}],"title":"Min Trace At","description":"(x, y) mm of the narrowest trace"},"min_trace_layer":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Min Trace Layer"},"min_trace_segment_mm":{"anyOf":[{"prefixItems":[{"prefixItems":[{"type":"number"},{"type":"number"}],"type":"array","maxItems":2,"minItems":2},{"prefixItems":[{"type":"number"},{"type":"number"}],"type":"array","maxItems":2,"minItems":2}],"type":"array","maxItems":2,"minItems":2},{"type":"null"}],"title":"Min Trace Segment Mm"},"min_spacing_at_mm":{"anyOf":[{"prefixItems":[{"type":"number"},{"type":"number"}],"type":"array","maxItems":2,"minItems":2},{"type":"null"}],"title":"Min Spacing At Mm"},"min_spacing_layer":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Min Spacing Layer"},"min_spacing_segment_mm":{"anyOf":[{"prefixItems":[{"prefixItems":[{"type":"number"},{"type":"number"}],"type":"array","maxItems":2,"minItems":2},{"prefixItems":[{"type":"number"},{"type":"number"}],"type":"array","maxItems":2,"minItems":2}],"type":"array","maxItems":2,"minItems":2},{"type":"null"}],"title":"Min Spacing Segment Mm"},"has_top_silk":{"type":"boolean","title":"Has Top Silk"},"has_bottom_silk":{"type":"boolean","title":"Has Bottom Silk"},"has_top_mask":{"type":"boolean","title":"Has Top Mask"},"has_bottom_mask":{"type":"boolean","title":"Has Bottom Mask"},"has_top_paste":{"type":"boolean","title":"Has Top Paste"},"has_bottom_paste":{"type":"boolean","title":"Has Bottom Paste"},"has_netlist":{"type":"boolean","title":"Has Netlist"},"smd_pads_top":{"type":"integer","title":"Smd Pads Top","default":0},"smd_pads_bottom":{"type":"integer","title":"Smd Pads Bottom","default":0}},"type":"object","required":["copper_layer_count","inner_layer_count","has_top_silk","has_bottom_silk","has_top_mask","has_bottom_mask","has_top_paste","has_bottom_paste","has_netlist"],"title":"Metrics"},"MlPrediction":{"properties":{"board_class":{"type":"string","enum":["standard","advanced","hdi"],"title":"Board Class"},"board_class_confidence":{"type":"number","maximum":1.0,"minimum":0.0,"title":"Board Class Confidence"},"complexity_score":{"type":"number","maximum":10.0,"minimum":1.0,"title":"Complexity Score"},"model_version":{"type":"string","title":"Model Version"}},"type":"object","required":["board_class","board_class_confidence","complexity_score","model_version"],"title":"MlPrediction"},"PadSummary":{"properties":{"annular_ring":{"$ref":"#/components/schemas/AnnularRingStats"},"smd_pads_top":{"type":"integer","title":"Smd Pads Top","default":0},"smd_pads_bottom":{"type":"integer","title":"Smd Pads Bottom","default":0},"tht_pads":{"type":"integer","title":"Tht Pads","description":"Copper flashes that sit on a drilled hole (outer layers)","default":0},"min_smd_pad_mm":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Min Smd Pad Mm"},"min_smd_pad_at":{"anyOf":[{"prefixItems":[{"type":"number"},{"type":"number"}],"type":"array","maxItems":2,"minItems":2},{"type":"null"}],"title":"Min Smd Pad At"},"min_smd_pad_layer":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Min Smd Pad Layer"},"min_smd_pad_axis":{"anyOf":[{"type":"string","enum":["x","y"]},{"type":"null"}],"title":"Min Smd Pad Axis","description":"Axis of the pad's smallest dimension (the dimension line is drawn along it)"},"min_annular_ring_mm":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Min Annular Ring Mm","description":"min (pad - hole) / 2 over all THT pads"},"source":{"type":"string","enum":["x2_attributes","geometry","none"],"title":"Source","default":"none"}},"type":"object","title":"PadSummary"},"PcbReview":{"properties":{"summary":{"type":"string","title":"Summary","description":"2-4 sentence plain-language description of the board"},"board_class":{"type":"string","enum":["standard","advanced","hdi"],"title":"Board Class","description":"Fabrication capability class implied by the smallest features"},"recommended_stackup":{"type":"string","title":"Recommended Stackup","description":"e.g. '2-layer, 1.6 mm FR-4, 1 oz copper'"},"suggested_surface_finish":{"type":"string","title":"Suggested Surface Finish"},"suggested_solder_mask_color":{"type":"string","title":"Suggested Solder Mask Color"},"manufacturing_notes":{"items":{"type":"string"},"type":"array","title":"Manufacturing Notes"},"dfm_findings":{"items":{"$ref":"#/components/schemas/DfmFinding"},"type":"array","title":"Dfm Findings"},"questions_for_customer":{"items":{"type":"string"},"type":"array","title":"Questions For Customer","description":"Info the fab still needs before quoting"},"estimated_complexity_score":{"type":"integer","maximum":10.0,"minimum":1.0,"title":"Estimated Complexity Score"}},"type":"object","required":["summary","board_class","recommended_stackup","suggested_surface_finish","suggested_solder_mask_color","manufacturing_notes","dfm_findings","questions_for_customer","estimated_complexity_score"],"title":"PcbReview","description":"Expert review produced by Claude from the deterministic metrics."},"Placement":{"properties":{"ref":{"type":"string","title":"Ref"},"value":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Value"},"package":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Package"},"x_raw":{"type":"number","title":"X Raw"},"y_raw":{"type":"number","title":"Y Raw"},"x_mm":{"type":"number","title":"X Mm"},"y_mm":{"type":"number","title":"Y Mm"},"rotation":{"type":"number","title":"Rotation","default":0.0},"side":{"type":"string","enum":["top","bottom"],"title":"Side","default":"top"},"row":{"type":"integer","title":"Row"}},"type":"object","required":["ref","x_raw","y_raw","x_mm","y_mm","row"],"title":"Placement","description":"One row of the pick-and-place (centroid) file, in the file's own units and in mm."},"PnpFile":{"properties":{"file":{"type":"string","title":"File"},"format":{"type":"string","title":"Format","description":"kicad-pos, altium, eagle-mnt, csv, ..."},"unit":{"type":"string","enum":["mm","mil","inch","unknown"],"title":"Unit","default":"unknown"},"columns":{"additionalProperties":{"type":"string"},"type":"object","title":"Columns","description":"role -> header text as found in the file"},"rows":{"type":"integer","title":"Rows","default":0},"placements":{"items":{"$ref":"#/components/schemas/Placement"},"type":"array","title":"Placements"},"warnings":{"items":{"type":"string"},"type":"array","title":"Warnings"}},"type":"object","required":["file","format"],"title":"PnpFile"},"Provenance":{"properties":{"agent":{"type":"string","title":"Agent"},"version":{"type":"string","title":"Version"},"ms":{"type":"integer","title":"Ms"},"at":{"type":"number","title":"At"},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note"}},"type":"object","required":["agent","version","ms","at"],"title":"Provenance","description":"Which sub-agent version produced which part of a job, and how long it took."},"QuoteRow":{"properties":{"no":{"type":"integer","title":"No"},"spec":{"type":"string","title":"Spec"},"value":{"type":"string","title":"Value"},"source":{"type":"string","enum":["measured","derived","assumed","document","unknown"],"title":"Source"},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note","description":"Evidence, or what to confirm with the customer"},"loc":{"anyOf":[{"$ref":"#/components/schemas/SpecLocation"},{"type":"null"}]},"doc_ref":{"anyOf":[{"$ref":"#/components/schemas/DocRef"},{"type":"null"}],"description":"For values read from a document: the page and box to show"},"builtin":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Builtin","description":"The built-in default this row would get (only for rows the files did not answer)"},"settable":{"type":"boolean","title":"Settable","description":"True when quote settings (prefill/empty) apply to this row","default":false},"value_mm":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Value Mm","description":"Numeric length behind `value`, so it can be shown in mm / mil / inch"},"size_mm":{"anyOf":[{"prefixItems":[{"type":"number"},{"type":"number"}],"type":"array","maxItems":2,"minItems":2},{"type":"null"}],"title":"Size Mm","description":"W x H behind `value` (board size)"}},"type":"object","required":["no","spec","value","source"],"title":"QuoteRow","description":"One row of the customer quote sheet (specifications-*.xlsx template). `spec` is the template label verbatim."},"QuoteSettings":{"properties":{"specs":{"additionalProperties":{"$ref":"#/components/schemas/QuoteSpecSetting"},"type":"object","title":"Specs","description":"Keyed by the template spec label"},"units":{"type":"string","enum":["mm","mil","inch"],"title":"Units","description":"Preferred unit for lengths in the quote sheet and specs","default":"mm"}},"type":"object","title":"QuoteSettings"},"QuoteSpecSetting":{"properties":{"mode":{"type":"string","enum":["prefill","empty"],"title":"Mode","default":"prefill"},"default":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Default","description":"Custom default text; None = the built-in fab default"},"units":{"anyOf":[{"type":"string","enum":["mm","mil","inch"]},{"type":"null"}],"title":"Units","description":"Unit for this spec's length; None = the sheet-level preference"}},"type":"object","title":"QuoteSpecSetting","description":"How one quote-sheet spec is filled when the files/drawing do not answer it."},"Renders":{"properties":{"available":{"items":{"type":"string"},"type":"array","title":"Available","description":"'top', 'bottom', and per-layer keys"},"inline":{"additionalProperties":{"type":"string"},"type":"object","title":"Inline","description":"key -> SVG, only when ?renders=inline"}},"type":"object","title":"Renders","description":"Renders are produced on demand by GET /jobs/{id}/render/{key}.svg (keys use '_' for ' ')."},"ReviewMeta":{"properties":{"source":{"type":"string","enum":["rules","ml","llm"],"title":"Source"},"model":{"type":"string","title":"Model","description":"rules engine version, ML model version, or Claude model id"},"duration_ms":{"type":"integer","title":"Duration Ms"},"input_tokens":{"type":"integer","title":"Input Tokens","default":0},"output_tokens":{"type":"integer","title":"Output Tokens","default":0},"ml":{"anyOf":[{"$ref":"#/components/schemas/MlPrediction"},{"type":"null"}]}},"type":"object","required":["source","model","duration_ms"],"title":"ReviewMeta"},"RingSample":{"properties":{"ring_mm":{"type":"number","title":"Ring Mm"},"x_mm":{"type":"number","title":"X Mm","description":"Hole centre"},"y_mm":{"type":"number","title":"Y Mm"},"side":{"type":"string","title":"Side"},"hole_mm":{"type":"number","title":"Hole Mm"},"pad_mm":{"type":"number","title":"Pad Mm","description":"Smallest dimension of the pad aperture at that hole"},"offset_mm":{"type":"number","title":"Offset Mm","description":"Distance between pad centre and hole centre (drill drift / registration)","default":0.0},"dir":{"prefixItems":[{"type":"number"},{"type":"number"}],"type":"array","maxItems":2,"minItems":2,"title":"Dir","description":"Unit vector from the hole centre towards the thinnest copper","default":[1.0,0.0]}},"type":"object","required":["ring_mm","x_mm","y_mm","side","hole_mm","pad_mm"],"title":"RingSample","description":"One drilled pad. ring = copper left on the worst side: (R_pad - R_hole) - |pad centre - hole centre| for a\nround pad; for a w x h pad the smaller of the two axis margins minus the hole radius."},"SpecItem":{"properties":{"group":{"type":"string","title":"Group"},"key":{"type":"string","title":"Key"},"label":{"type":"string","title":"Label"},"value":{"type":"string","title":"Value","description":"Display string, e.g. '1.60 mm (default)'"},"raw":{"anyOf":[{"type":"number"},{"type":"string"},{"type":"boolean"},{"type":"null"}],"title":"Raw"},"unit":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Unit"},"source":{"type":"string","enum":["measured","derived","assumed","document","unknown"],"title":"Source"},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note"},"loc":{"anyOf":[{"$ref":"#/components/schemas/SpecLocation"},{"type":"null"}]},"doc_ref":{"anyOf":[{"$ref":"#/components/schemas/DocRef"},{"type":"null"}],"description":"For values read from a document: the page and box to show"}},"type":"object","required":["group","key","label","value","source"],"title":"SpecItem","description":"One line of the quote sheet. `assumed` means a fab default was used because the files did not say."},"SpecLocation":{"properties":{"x_mm":{"type":"number","title":"X Mm"},"y_mm":{"type":"number","title":"Y Mm"},"w_mm":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"W Mm","description":"Box size when the spec is an area (pour, flex section, board)"},"h_mm":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"H Mm"},"layer":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Layer","description":"Layer key to show, e.g. 'bottom copper'"},"layers":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Layers","description":"Several layer keys to show together (a via span: its copper layers + drill)"},"zoom_mm":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Zoom Mm","description":"Suggested viewport size around the point"},"segment":{"anyOf":[{"prefixItems":[{"prefixItems":[{"type":"number"},{"type":"number"}],"type":"array","maxItems":2,"minItems":2},{"prefixItems":[{"type":"number"},{"type":"number"}],"type":"array","maxItems":2,"minItems":2}],"type":"array","maxItems":2,"minItems":2},{"type":"null"}],"title":"Segment","description":"The measured span, edge to edge in mm (a gap between two copper edges, a trace width, a ring...) - drawn as a dimension line"},"measure":{"anyOf":[{"type":"string","enum":["gap","width","ring","hole","pitch","clearance"]},{"type":"null"}],"title":"Measure","description":"What the segment measures"}},"type":"object","required":["x_mm","y_mm"],"title":"SpecLocation","description":"Where on the board a spec value comes from, so the viewer can jump to it."},"StackupLayer":{"properties":{"position":{"type":"integer","title":"Position"},"kind":{"type":"string","enum":["silk","paste","mask","copper","dielectric"],"title":"Kind"},"name":{"type":"string","title":"Name"},"layer_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Layer Key"},"file":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"File"},"thickness_um":{"type":"number","title":"Thickness Um"},"assumed":{"type":"boolean","title":"Assumed","description":"Thickness is a default unless a stackup file said otherwise","default":true},"material":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Material"}},"type":"object","required":["position","kind","name","thickness_um"],"title":"StackupLayer"},"TrainReport":{"properties":{"n_real":{"type":"integer","title":"N Real"},"n_synthetic":{"type":"integer","title":"N Synthetic"},"class_cv_accuracy":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Class Cv Accuracy"},"complexity_cv_mae":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Complexity Cv Mae"},"model_path":{"type":"string","title":"Model Path"},"version":{"type":"string","title":"Version"}},"type":"object","required":["n_real","n_synthetic","class_cv_accuracy","complexity_cv_mae","model_path","version"],"title":"TrainReport"},"UnitsSummary":{"properties":{"canonical":{"type":"string","title":"Canonical","default":"mm"},"files_mm":{"type":"integer","title":"Files Mm","default":0},"files_inch":{"type":"integer","title":"Files Inch","default":0},"files_unknown":{"type":"integer","title":"Files Unknown","default":0},"mixed":{"type":"boolean","title":"Mixed","description":"Layers declare different units (allowed by the spec, but a common source of misalignment)","default":false},"drill_alignment":{"type":"string","enum":["ok","suspect","n/a"],"title":"Drill Alignment","description":"Drill extents vs copper extents","default":"n/a"},"per_file":{"items":{"$ref":"#/components/schemas/FileUnits"},"type":"array","title":"Per File"},"warnings":{"items":{"type":"string"},"type":"array","title":"Warnings"}},"type":"object","title":"UnitsSummary"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"VerificationCheck":{"properties":{"name":{"type":"string","title":"Name"},"vector":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Vector","description":"Value measured from the Gerber vectors"},"image":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Image","description":"Value re-measured on the raster"},"unit":{"type":"string","title":"Unit","default":"mm"},"delta":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Delta"},"tolerance":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Tolerance","description":"max(2 px, 3 %)"},"status":{"type":"string","enum":["agree","narrower","mismatch","n/a"],"title":"Status","description":"narrower = raster found copper thinner than any stroked aperture (pour necks, thermal spokes)"}},"type":"object","required":["name","status"],"title":"VerificationCheck"}}}}