← Commit history

Add MIT mechanical service-access review prototype and tool guidance

John Lauer ·1195dc3f10 ·4d ago ·parent 2e3b460
7 files changed +172−4
Cargo.lockadded+105
@@ -0,0 +1,105 @@+# This file is automatically @generated by Cargo.+# It is not intended for manual editing.+version = 4++[[package]]+name = "adom-aiflow-mechanical"+version = "0.1.0"+dependencies = [+ "serde_json",+]++[[package]]+name = "itoa"+version = "1.0.18"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"++[[package]]+name = "memchr"+version = "2.8.3"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98"++[[package]]+name = "proc-macro2"+version = "1.0.107"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9"+dependencies = [+ "unicode-ident",+]++[[package]]+name = "quote"+version = "1.0.47"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001"+dependencies = [+ "proc-macro2",+]++[[package]]+name = "serde"+version = "1.0.229"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba"+dependencies = [+ "serde_core",+]++[[package]]+name = "serde_core"+version = "1.0.229"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48"+dependencies = [+ "serde_derive",+]++[[package]]+name = "serde_derive"+version = "1.0.229"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348"+dependencies = [+ "proc-macro2",+ "quote",+ "syn",+]++[[package]]+name = "serde_json"+version = "1.0.154"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "e7e9cc8b1b85264074fbcc02a88680c4096b1e47df8f739dceb03bf482f04bd6"+dependencies = [+ "itoa",+ "memchr",+ "serde",+ "serde_core",+ "zmij",+]++[[package]]+name = "syn"+version = "3.0.9"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "d78c8dee4c7bf0e14673097256fed6142ce9d3b85a408189d07482442145823b"+dependencies = [+ "proc-macro2",+ "quote",+ "unicode-ident",+]++[[package]]+name = "unicode-ident"+version = "1.0.27"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "a2c754d6c33795a1c324727428e5a7dedb5b06195f9890bdbcba760d3e246563"++[[package]]+name = "zmij"+version = "1.0.23"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b"
Cargo.tomladded+7
@@ -0,0 +1,7 @@+[package]+name = "adom-aiflow-mechanical"+version = "0.1.0"+edition = "2021"+license = "MIT"+[dependencies]+serde_json = "1"
LICENSEadded+9
@@ -0,0 +1,9 @@+MIT License++Copyright (c) 2026 Adom Industries Inc.++Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:++The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
README.md+4−2
@@ -1,3 +1,5 @@-# Adom Aiflow Mechanical+# adom-aiflow-mechanical -Mechanical assembly and service-access review with dynamic AI hints+MIT-licensed initial Rust review CLI and dynamic guidance. Local prototype; not yet published or integrated into shared AIFlow.++See [skill](SKILL.md). Run `cargo test` and `cargo build --release`; invoke `target/release/adom-aiflow-mechanical lint <review.json>`. Exit 0 means declared review checks pass, 1 unresolved findings, 2 input error. It does not independently validate CAD or physical assembly.
SKILL.mdadded+20
@@ -0,0 +1,20 @@+---+name: adom-aiflow-mechanical+description: Review PCB mechanical assembly and service access, fastener tools, wiring and removal order. Optional tool animation; mandatory evidence for required service paths.+---+# Mechanical assembly review++Use alongside AIFlow; this tool never replaces electrical, thermal or probing gates.+Run `adom-aiflow-mechanical lint assembly-access.json` after placement or mechanical changes and before final assembly export. Exit 1 means unresolved review work, not permission to waive checks.++Inventory every fastener and removable connector. Specify exact drive type, tool shaft and handle envelopes, head/nut dimensions, thread engagement, washers, preload assumptions and retention. Include approach, engagement, loosening, withdrawal and part extraction. Check the actual scaffold, pincers, enclosure, wires and neighboring components. An aligned hole alone is insufficient.++Access holes must pass the largest required tool or extracted part, plus explicit radial tolerance; add native NPTH, copper/component keepouts and side-appropriate service labels. Bind evidence to current board and assembly hashes. Never mark a Boolean verified merely to satisfy the linter: supply a linked CAD check report and review it.++For angled access, select an actual ball-end hex tool and verify manufacturer angle/torque limits. Prefer straight access for final torque. Model tweezers, captive hardware or removal tools when the assembly sequence requires them. Check that the removed part can leave after the screw is loose.++Tool animation is optional. If useful, animate approach, engagement, fastener withdrawal and extraction using the actual tool envelope, with slow pauses at constraints. Label illustrative motion; a film is not collision or physical-fit evidence. Never force a video for a user who only needs manufacturing files.++For harnesses, identify real factory leads, contacts and connector orientation. Compare short direct routes with connector relocation; include service slack, minimum bend radius, strain relief, crimp allowance and minimum supplied lead length. Avoid duplicate decorative wires. Re-run electrical routing, DRC, current analysis and assembled probing after relocation.++This initial binary checks declared dimensions and review completeness. It does not itself calculate 3D swept collisions. Do not describe it as a geometry solver or independently verified assembly.
page.json+2−2
@@ -15,7 +15,7 @@     "email": "[email protected]"   },   "tags": [],-  "license": "proprietary",+  "license": "MIT",   "visibility": {     "public": true   },@@ -33,4 +33,4 @@   },   "skills": [],   "org": "adom"-}\ No newline at end of file+}
src/main.rsadded+25
@@ -0,0 +1,25 @@+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);}}