app
AI Flow
Public Made by Adomby adom
Adom's AI Flow: a tool to help the AI follow all of the steps it takes to build a board.
← All Pull Requests
AI Flow 0.2.54: the thermal screen stops on a body whose heat never reaches the board #69
Merges
aiflow-lane-0.2.54 → mainThe thermal field screen now stops on adom-fields' solid-uncoupled finding at high severity: a body with boardContactM2kW set but no face on the copper takes 0 W, and an unattended run would still have passed. The medium form doesn't stop it.
Tested: 600 Rust tests and the Python tests pass. Real solves on adom-fields 0.10.6 on the 12 V buck board: with a body 1.4 mm below the copper, 0.2.53 passed the screen and this build stops and names the body. With a body on the copper and a real contact, it carries 0.187 W and the screen passes.
🤖 Generated with Claude Code
Diff Skip to comments
Cargo.lock+10−10@@ -4,7 +4,7 @@ version = 4 [[package]] name = "adom-aiflow"-version = "0.2.53"+version = "0.2.54" dependencies = [ "aiflow-analyze", "aiflow-board",@@ -25,7 +25,7 @@ dependencies = [ [[package]] name = "aiflow-analyze"-version = "0.2.53"+version = "0.2.54" dependencies = [ "aiflow-board", "serde",@@ -35,7 +35,7 @@ dependencies = [ [[package]] name = "aiflow-board"-version = "0.2.53"+version = "0.2.54" dependencies = [ "roxmltree", "serde",@@ -44,7 +44,7 @@ dependencies = [ [[package]] name = "aiflow-bridge"-version = "0.2.53"+version = "0.2.54" dependencies = [ "aiflow-board", "serde",@@ -53,7 +53,7 @@ dependencies = [ [[package]] name = "aiflow-copper"-version = "0.2.53"+version = "0.2.54" dependencies = [ "aiflow-board", "aiflow-grid",@@ -63,7 +63,7 @@ dependencies = [ [[package]] name = "aiflow-grid"-version = "0.2.53"+version = "0.2.54" dependencies = [ "aiflow-board", "serde",@@ -72,7 +72,7 @@ dependencies = [ [[package]] name = "aiflow-place"-version = "0.2.53"+version = "0.2.54" dependencies = [ "aiflow-board", "serde",@@ -81,7 +81,7 @@ dependencies = [ [[package]] name = "aiflow-pours"-version = "0.2.53"+version = "0.2.54" dependencies = [ "aiflow-board", "aiflow-copper",@@ -91,7 +91,7 @@ dependencies = [ [[package]] name = "aiflow-router"-version = "0.2.53"+version = "0.2.54" dependencies = [ "aiflow-board", "aiflow-grid",@@ -101,7 +101,7 @@ dependencies = [ [[package]] name = "aiflow-run"-version = "0.2.53"+version = "0.2.54" dependencies = [ "serde", "serde_json",
Cargo.toml+1−1@@ -14,7 +14,7 @@ members = [ ] [workspace.package]-version = "0.2.53"+version = "0.2.54" edition = "2021" license = "MIT" repository = "https://wiki.adom.inc/adom/adom-aiflow"
crates/aiflow-analyze/src/lib.rs+15−1@@ -481,7 +481,7 @@ pub fn field_screen_with_acks(fields: &Value, spec: &Value, board_bytes: &[u8], // a neck finding at an acknowledged point is the same reviewed peak; barrel findings never are let acked_neck = |i: &Value| i["kind"]=="current-neck" && covered.iter().any(|c| c["net"]==i["net"] && i["at"][0].as_f64().zip(i["at"][1].as_f64()).is_some_and(|(x,y)| (x-c["at"][0].as_f64().unwrap_or(f64::NAN)).hypot(y-c["at"][1].as_f64().unwrap_or(f64::NAN)) <= current_acks::TOLERANCE_MM));- let relevant: Vec<_>=issues.iter().filter(|i| if kind=="current" { (i["kind"]=="current-neck" && !acked_neck(i)) || i["kind"]=="current-barrel" } else { i["kind"]=="tab-rise" || i["kind"]=="thermal-vias" }).collect();+ let relevant: Vec<_>=issues.iter().filter(|i| if kind=="current" { (i["kind"]=="current-neck" && !acked_neck(i)) || i["kind"]=="current-barrel" } else { i["kind"]=="tab-rise" || i["kind"]=="thermal-vias" || (i["kind"]=="solid-uncoupled" && i["severity"]=="high") }).collect(); if !relevant.is_empty() { return Err(relevant.iter().map(|i|i["what"].as_str().unwrap_or("unresolved field finding")).collect::<Vec<_>>().join("; ")); } Ok(covered) }@@ -672,6 +672,20 @@ mod field_screen_tests { f["board"]["copperLayers"]=json!(["F.Cu","B.Cu"]); assert!(field_screen(&f,&spec,B4,b"spec","current").unwrap_err().contains("copper stack")); }+ /// adom-fields 0.10.6: a body meant to touch the board that touches no copper takes 0 W, so the+ /// temperatures read cooler or hotter than the board really runs. That is a false thermal result.+ /// The medium kind, a body with no heat and no path to the board, can be deliberate and does not stop it.+ #[test]+ fn a_body_that_never_reaches_the_board_stops_the_thermal_screen() {+ let spec=json!({"hotMaxRiseC":20,"loads":{"VCC":{"amps":2}},"hot":{"Q1":{"watts":5,"tabNet":"VCC"}}});+ let mut f=thermal_report();+ assert!(field_screen(&f,&spec,b"board",b"spec","thermal").is_ok(), "the report itself is clean");+ f["issues"]=json!([{"severity":"high","kind":"solid-uncoupled","what":"carrier: boardContactM2kW is set, but no face is on the copper"}]);+ assert!(field_screen(&f,&spec,b"board",b"spec","thermal").unwrap_err().contains("carrier"));+ assert!(field_screen(&f,&spec,b"board",b"spec","current").is_ok(), "not a current finding");+ f["issues"]=json!([{"severity":"medium","kind":"solid-uncoupled","what":"shield: no heat of its own and no path to the board"}]);+ assert!(field_screen(&f,&spec,b"board",b"spec","thermal").is_ok());+ } #[test] fn fresh_solve_requires_identity_coverage_and_no_relevant_findings() { let spec=serde_json::json!({"loads":{"VCC":{"amps":2}},"hot":{"Q1":{"watts":1}}});
docs/release-0.2.54.mdadded+11@@ -0,0 +1,11 @@+# AI Flow 0.2.54 (2026-11-05)++**The thermal check no longer passes a body whose heat never reaches the board.** adom-fields 0.10.6 reports `solid-uncoupled` when a body has `boardContactM2kW` set but no face on the copper, so it takes 0 W. The field screen now stops on that finding at `high` severity. Like the other thermal findings, it shows in `analyze thermal` as not passed, with the Fields message naming the body.++The `medium` form, a body with no heat of its own and no path to the board, doesn't stop the screen, because it can be deliberate.++**Checked with real solves on adom-fields 0.10.6,** on the 12 V buck molecule board with a body under it:+- Body 1.4 mm below the copper: 0.2.53 said the field screen passed; this build stops and names the body.+- Body on the copper with a real contact: it carried 0.187 W, no `solid-uncoupled`, and the field screen passed.++Nothing else in adom-fields 0.10.6 needed a change here. AI Flow doesn't read its grid size or the new `return` and `onCopper` fields. A board that gains a grid column can shift its numbers slightly, per the Fields notes, so a value right at a limit can cross it.
package.json+1−1@@ -1,7 +1,7 @@ { "slug": "adom-aiflow", "type": "app",- "version": "0.2.53",+ "version": "0.2.54", "title": "AI Flow", "description": "Adom's AI Flow: a tool to help the AI follow all of the steps it takes to build a board. One Rust binary with a crate per step (placement helpers, a grid router with Kelvin taps, pours with keepouts, KiCad's DRC gate, live landing through the KiCad Bridge, copper measurement, current and thermal analysis) and a finish line that refuses an unfinished board. Every command answers with hints for the AI; every turn, its thinking time and every rework loop go into run.jsonl, so Claude, Codex and any other engine are compared on the same flow. KiCad, Fusion 360 and Altium Designer today (the same steps and gates through each tool's bridge); Adom's own web apps next.", "summary": "Adom's AI Flow: a tool to help the AI follow all of the steps it takes to build a board. The AI thinks its way from placement through routing, pours, current and thermal analysis to a delivered video; the binary does the fast, deterministic parts of every step, hands back hints, and keeps a ledger of every turn, every return to an earlier step, and the clock from the prompt to done.",
page.json+1−1@@ -1,7 +1,7 @@ { "slug": "adom-aiflow", "type": "app",- "version": "0.2.53",+ "version": "0.2.54", "title": "AI Flow", "description": "Adom's AI Flow: a tool to help the AI follow all of the steps it takes to build a board. One Rust binary with a crate per step (placement helpers, a grid router with Kelvin taps, pours with keepouts, KiCad's DRC gate, live landing through the KiCad Bridge, copper measurement, current and thermal analysis) and a finish line that refuses an unfinished board. Every command answers with hints for the AI; every turn, its thinking time and every rework loop go into run.jsonl, so Claude, Codex and any other engine are compared on the same flow. KiCad, Fusion 360 and Altium Designer today (the same steps and gates through each tool's bridge); Adom's own web apps next.", "summary": "Adom's AI Flow: a tool to help the AI follow all of the steps it takes to build a board. The AI thinks its way from placement through routing, pours, current and thermal analysis to a delivered video; the binary does the fast, deterministic parts of every step, hands back hints, and keeps a ledger of every turn, every return to an earlier step, and the clock from the prompt to done.",
Comments
Log in to comment.
No comments yet.