app
Adom Chipsmith
Public Made by Adomby adom
STEP-native chip validator — 5-source cross-validation, OCCT-generated copyright-free 3D models with embedded signal annotations, datasheet-to-STEP pipeline.
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
use crate::cli::{err, hint, ok, DEFAULT_PORT};
use crate::cli::eval::eval_snippet;
use anyhow::Result;
use clap::Parser;
/// Sign off the currently-loaded chip — runs the same gate-check flow as
/// the Sign-off button. Writes <mpn>.chipsmith.json sidecar and (if the
/// service-step2glb /bake endpoint is deployed) the canonical
/// <mpn>.chipsmith.step. Per the plan, every downstream Adom tool must
/// prefer the baked .chipsmith.step over the original input.
#[derive(Parser)]
pub struct Args {
/// Skip the canSignOff() gate check and force the sidecar write
/// anyway. ONLY for triage / dry-run debugging — bypasses pin-1 +
/// measurement + footprint validation.
#[arg(long)]
pub force: bool,
#[arg(long, default_value_t = DEFAULT_PORT)]
pub port: u16,
}
pub fn run(args: Args) -> Result<()> {
let snippet = if args.force {
// Skip canSignOff — invoke the underlying API directly.
"{ \
const payload = { \
mpn: window.adomChipsmith?.state?.spec?.mpn, \
measurements: window.adomChipsmith?.state?.measurements, \
user_placed_pin1: window.adomChipsmith?.state?.userPin1Corner ? { corner: window.adomChipsmith.state.userPin1Corner } : null, \
decorative_product_names: window.adomChipsmith?.state?.decorativeProductNames || [], \
signed_at: new Date().toISOString(), \
forced: true, \
}; \
const r = await fetch('api/signoff', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify(payload) }); \
return r.json(); \
}".to_string()
} else {
"return await window.adomChipsmith.signoff.signOff();".to_string()
};
let v = eval_snippet(&snippet, 30, args.port, true)?;
if let Some(blockers) = v.get("blockers").and_then(|x| x.as_array()) {
if !blockers.is_empty() {
err(format!("sign-off blocked by {} gate(s)", blockers.len()));
for b in blockers {
if let Some(s) = b.as_str() { hint(s.to_string()); }
}
hint("re-run with --force to bypass gates (debug only)".to_string());
return Err(anyhow::anyhow!("blocked"));
}
}
if let Some(e) = v.get("error").and_then(|x| x.as_str()) {
err(format!("sign-off: {e}"));
return Err(anyhow::anyhow!("signoff failed"));
}
if let Some(p) = v.get("sidecar_path").and_then(|x| x.as_str()) {
ok(format!("sidecar: {p}"));
}
if let Some(s) = v.get("bake_status").and_then(|x| x.as_str()) {
if !s.is_empty() { ok(format!("bake: {s}")); }
}
if v.get("step_baked").and_then(|x| x.as_bool()).unwrap_or(false) {
if let Some(p) = v.get("step_path").and_then(|x| x.as_str()) {
ok(format!("baked .chipsmith.step: {p}"));
}
}
ok(format!("sign-off complete"));
Ok(())
}