app
Adom Aiflow Mechanical
Public Made by Adomby adom
Mechanical assembly and service-access review with dynamic AI hints
main
use serde_json::{json, Value};
use std::{env,fs,process};
fn lint(v:&Value)->Value {
let mut findings=vec![];
let items=v["fasteners"].as_array();
if items.map_or(true, |a|a.is_empty()){findings.push(json!({"severity":"error","id":"inventory","hint":"Inventory every service fastener, tool and removal sequence."}));}
for f in items.into_iter().flatten(){
let id=f["id"].as_str().unwrap_or("unnamed");
let mut add=|key:&str,hint:&str|findings.push(json!({"severity":"error","id":id,"check":key,"hint":hint}));
for key in ["tool","approach","removalSequence","retention"] {if f[key].as_str().map_or(true,|s|s.trim().is_empty()){add(key,"Specify the actual tool, approach, retention and ordered removal operations; include tweezers where needed.");}}
if f["requiresAccessHole"]==true {
let diameter=f["holeDiameterMm"].as_f64().unwrap_or(0.);
let tool=f["toolEnvelopeDiameterMm"].as_f64().unwrap_or(0.);
let head=f["extractedPartDiameterMm"].as_f64().unwrap_or(0.);
let clearance=f["radialClearanceMm"].as_f64().unwrap_or(0.);
if ![diameter,tool,head,clearance].iter().all(|x| x.is_finite() && *x>0.) || diameter < tool.max(head)+2.*clearance {add("accessDiameter","Provide a real board opening that passes both tool and extracted hardware with explicit radial clearance.");}
}
if f["angleDeg"].as_f64().unwrap_or(0.)!=0. && f["manufacturerToolAngleVerified"]!=true {add("angledTool","Verify the selected ball-end driver angle and torque limits; do not infer access from a straight cylinder.");}
if f["sweptVolumeVerified"]!=true {add("sweptVolume","Check approach, engagement, loosening and extraction swept volumes against PCB, components, wires, scaffold and enclosure.");}
if f["boardRevisionVerified"]!=true {add("revision","Bind access-hole and collision evidence to the current PCB and assembly hashes.");}
}
json!({"schemaVersion":1,"passed":findings.is_empty(),"findings":findings,"animationRequired":false,"hint":"Optional tool animation helps review assembly; it does not replace swept-volume checks or qualify physical fit."})
}
fn main(){let a:Vec<_>=env::args().collect();if a.len()!=3||a[1]!="lint"{eprintln!("Usage: adom-aiflow-mechanical lint assembly-access.json");process::exit(2)}let r=fs::read_to_string(&a[2]).map_err(|e|e.to_string()).and_then(|s|serde_json::from_str(&s).map_err(|e|e.to_string()));match r{Ok(v)=>{let out=lint(&v);println!("{}",serde_json::to_string_pretty(&out).unwrap());if out["passed"]!=true{process::exit(1)}},Err(e)=>{eprintln!("ERROR: {e}");process::exit(2)}}}
#[cfg(test)] mod tests{use super::*;#[test]fn missing_inventory_fails(){assert_eq!(lint(&json!({}))["passed"],false)}#[test]fn optional_animation_does_not_waive_access(){let v=json!({"fasteners":[{"id":"sensor","tool":"2.5 mm hex","approach":"underside","removalSequence":"loosen, capture, extract","retention":"magnetic tray","requiresAccessHole":true,"holeDiameterMm":6.8,"toolEnvelopeDiameterMm":4.0,"extractedPartDiameterMm":5.5,"radialClearanceMm":0.5,"sweptVolumeVerified":true,"boardRevisionVerified":true}]});assert_eq!(lint(&v)["passed"],true);let mut bad=v.clone();bad["fasteners"][0]["holeDiameterMm"]=json!(5.5);assert_eq!(lint(&bad)["passed"],false);}}