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
0.2.14: Altium runs save the board at every step and before export #46
adom-aiflow 0.2.14
- Altium: the board and schematic are saved as the run goes. The Altium lane saved its documents once, when
altium schematicbuilt them. Placement, routing, pours, silkscreen and every fix after that lived only in Altium's open documents. In the 2026-10-20 run, the project folder handed over as "the Altium project on the desktop" held the empty board from 19:10. The finished board existed only in Altium's memory until it was saved by hand. (The Gerbers were right: the export works from the open documents.)- Every
stepchange in an Altium run now saves the schematic and the board (the board is left in front for the next step). A failed save prints a warning. altium exportsaves both before it writes the manufacturing set, and stops if a save fails, so the project on disk is the board that was exported.
- Every
- Verified live: a step change on DESKTOP-BAR6S0F rewrote both
Buck12V5V.SchDocandBuck12V5V.PcbDoc.
🤖 Generated with Claude Code
Diff Skip to comments
@@ -1,5524 +1,5536 @@⋯ 5094 unchanged lines ⋯ let known: Vec<&str> = known.iter().map(String::as_str).collect(); let mut clip_stopped = false; let prev = r.data["currentStep"].as_str().map(str::to_string);+ // an Altium run's edits live in the open documents until they are saved: a 2026-10-20 run saved+ // its board once, when it was built, and the project it handed over was that empty board. Every+ // step change saves them (the schematic, then the board, which is left in front)+ if let Some(pcb) = r.data["remoteBoard"].as_str().and_then(|b| b.strip_prefix("altium:")).filter(|_| prev.as_deref().map_or(false, |p| p != name.as_str())) {+ let br = bridge_of(&r, &cli);+ let sch = std::fs::read_to_string(dir.join("altium").join("project.json")).ok().and_then(|s| serde_json::from_str::<Value>(&s).ok()).and_then(|v| v["schematic"].as_str().map(str::to_string));+ for doc in sch.iter().map(String::as_str).chain(std::iter::once(pcb)) {+ let s = br.raw_call("altium_save", &json!({"filePath": doc}));+ if !Bridge::ok(&s) { eprintln!("WARNING: could not save {doc} ({}): save it in Altium (File > Save) before going on", s["errorCode"].as_str().or(s["error"].as_str()).unwrap_or("?")); }+ }+ } // the board's project page gets the step just left as its own sub-readme (evidence, screenshots, // usage) and a line in the README's build section, in the background so the step is not slowed if let (Some(pg), Some(pv)) = (r.data["projectPage"].as_str(), prev.as_deref()) {⋯ 421 unchanged lines ⋯ assert!(ffmpeg_ok(std::process::Command::new("sh").args(["-c", "exit 0"]))); } }+@@ -1,716 +1,722 @@⋯ 594 unchanged lines ⋯ if not prj or not pcb: err('no Altium project yet', ['Run `adom-aiflow altium schematic` first: the project holds the schematic, the board and the manufacturing OutJob.']) out = Path(a.out_dir) if a.out_dir else RUN / 'manufacturing' shutil.rmtree(out, ignore_errors=True); out.mkdir(parents=True)+ # the project handed over is what is on disk: save the open schematic and board first (a 2026-10-20 run+ # had saved its board only when it was built, so its project opened as the empty board)+ for d in [x for x in (st.get('schematic'), pcb) if x]:+ s = ab('altium_save', {'filePath': d})+ if not s.get('success'): err('could not save %s before the export: %s' % (d, s.get('error') or s.get('errorCode')), ['Save it in Altium (File > Save), then run `altium export` again.']) say('writing the manufacturing set from %s' % prj) r = ab('altium_export_manufacturing', {'projectPath': prj, 'pcbPath': pcb}, timeout=900) if not r.get('success') or not r.get('files'): err('the export wrote nothing: %s' % (r.get('error') or r.get('errorCode') or 'no files'), [r.get('_hint'), 'dialogs: %s' % json.dumps(r.get('dialogs'))[:300] if r.get('dialogs') else ''])⋯ 113 unchanged lines ⋯ main()+@@ -0,0 +1,7 @@+# adom-aiflow 0.2.14++- **Altium: the board and schematic are saved as the run goes.** The Altium lane saved its documents once, when `altium schematic` built them. Placement, routing, pours, silkscreen and every fix after that lived only in Altium's open documents. In the 2026-10-20 run, the project folder handed over as "the Altium project on the desktop" held the empty board from 19:10. The finished board existed only in Altium's memory until it was saved by hand. (The Gerbers were right: the export works from the open documents.)+ - Every `step` change in an Altium run now saves the schematic and the board (the board is left in front for the next step). A failed save prints a warning.+ - `altium export` saves both before it writes the manufacturing set, and stops if a save fails, so the project on disk is the board that was exported.+- Verified live: a step change on DESKTOP-BAR6S0F rewrote both `Buck12V5V.SchDoc` and `Buck12V5V.PcbDoc`.+@@ -1,94 +1,95 @@ { "slug": "adom-aiflow", "type": "app",- "version": "0.2.13",+ "version": "0.2.14", "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.",⋯ 84 unchanged lines ⋯ ], "license": "MIT" }+@@ -1,100 +1,100 @@ { "slug": "adom-aiflow", "type": "app",- "version": "0.2.13",+ "version": "0.2.14", "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.",⋯ 93 unchanged lines ⋯@@ -1,40 +1,41 @@⋯ 13 unchanged lines ⋯ ] [workspace.package]-version = "0.2.13"+version = "0.2.14" edition = "2021" license = "MIT" repository = "https://wiki.adom.inc/adom/adom-aiflow"⋯ 17 unchanged lines ⋯ lto = true codegen-units = 1 strip = true+@@ -1,648 +1,649 @@⋯ 3 unchanged lines ⋯ [[package]] name = "adom-aiflow"-version = "0.2.13"+version = "0.2.14" dependencies = [ "aiflow-analyze", "aiflow-board",⋯ 14 unchanged lines ⋯ [[package]] name = "aiflow-analyze"-version = "0.2.13"+version = "0.2.14" dependencies = [ "aiflow-board", "serde",⋯ 3 unchanged lines ⋯ [[package]] name = "aiflow-board"-version = "0.2.13"+version = "0.2.14" dependencies = [ "roxmltree", "serde",⋯ 2 unchanged lines ⋯ [[package]] name = "aiflow-bridge"-version = "0.2.13"+version = "0.2.14" dependencies = [ "aiflow-board", "serde",⋯ 2 unchanged lines ⋯ [[package]] name = "aiflow-copper"-version = "0.2.13"+version = "0.2.14" dependencies = [ "aiflow-board", "aiflow-grid",⋯ 3 unchanged lines ⋯ [[package]] name = "aiflow-grid"-version = "0.2.13"+version = "0.2.14" dependencies = [ "aiflow-board", "serde",⋯ 2 unchanged lines ⋯ [[package]] name = "aiflow-place"-version = "0.2.13"+version = "0.2.14" dependencies = [ "aiflow-board", "serde",⋯ 2 unchanged lines ⋯ [[package]] name = "aiflow-pours"-version = "0.2.13"+version = "0.2.14" dependencies = [ "aiflow-board", "aiflow-copper",⋯ 3 unchanged lines ⋯ [[package]] name = "aiflow-router"-version = "0.2.13"+version = "0.2.14" dependencies = [ "aiflow-board", "aiflow-grid",⋯ 3 unchanged lines ⋯ [[package]] name = "aiflow-run"-version = "0.2.13"+version = "0.2.14" dependencies = [ "serde", "serde_json",⋯ 538 unchanged lines ⋯ version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b"+
Comments
Log in to comment.
No comments yet.