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.
← Commit history
Bind Fields recording to the exact Pup session and refuse failed-tour proof
1 file changed
+11−8
crates/adom-aiflow/src/main.rs+11−8@@ -3964,16 +3964,17 @@ fn main() { let mut hwnd: Option<i64> = None; for _ in 0..40 { std::thread::sleep(std::time::Duration::from_secs(2));- let lw = br.call("desktop_list_windows", &json!({}));- // the relay wraps some answers as a JSON string under `output`+ let lw = br.call("pup_list_windows", &json!({})); let inner: Value = lw["output"].as_str().and_then(|t| serde_json::from_str(t).ok()).unwrap_or(Value::Null);- let d = lw.get("data").cloned().or_else(|| inner.get("data").cloned()).unwrap_or(lw.clone());- let wins = d["windows"].as_array().cloned().or_else(|| lw["windows"].as_array().cloned()).or_else(|| inner["windows"].as_array().cloned()).unwrap_or_default();- // the app's window, not a wiki page about it: the app titles itself exactly "Adom Fields"- hwnd = wins.iter().find(|w| w["title"].as_str().map(|t| (t == "Adom Fields" || t.starts_with("Adom Fields - ")) && !t.contains("Wiki") && !t.contains("wiki")).unwrap_or(false)).and_then(|w| w["hwnd"].as_i64().or_else(|| w["hwnd"].as_str().and_then(|h| h.parse().ok())));+ let sessions = lw["sessions"].as_array().or_else(|| inner["sessions"].as_array());+ // Only the session created by this invocation owns the recording target.+ // A title match can select another user's or another run's Fields window.+ hwnd = sessions.and_then(|rows| rows.iter().find(|w| w["sessionId"].as_str() == Some(sid.as_str())))+ .and_then(|w| w["hwnd"].as_i64().or_else(|| w["hwnd"].as_str().and_then(|h| h.parse().ok())))+ .filter(|h| *h > 0); if hwnd.is_some() { break; } }- let Some(win) = hwnd else { let _ = br.call("pup_close_window", &json!({"sessionId": sid})); err(&format!("the app's window did not appear on {} (no window titled Adom Fields{})", br.target, open_err.map(|e| format!("; pup said {e}")).unwrap_or_default()), &["`adom-bridge --target <box> pup_readiness` says whether pup is ready there; a browser_gone means pup's browser died: `pup_close_window` the old sessions or restart pup on the box.".into(), if preboard::proxy_is_local(&proxy) { format!("The URL {proxy} is a localhost proxy: only the machine hosting this container can open it. `tour fields --on <that machine>`.") } else { String::new() }, on_note.clone()]); };+ let Some(win) = hwnd else { let _ = br.call("pup_close_window", &json!({"sessionId": sid})); err(&format!("the app's window did not appear on {} (no window for this walkthrough session{})", br.target, open_err.map(|e| format!("; pup said {e}")).unwrap_or_default()), &["`adom-bridge --target <box> pup_readiness` says whether pup is ready there; a browser_gone means pup's browser died: `pup_close_window` the old sessions or restart pup on the box.".into(), if preboard::proxy_is_local(&proxy) { format!("The URL {proxy} is a localhost proxy: only the machine hosting this container can open it. `tour fields --on <that machine>`.") } else { String::new() }, on_note.clone()]); }; let save_to = std::fs::canonicalize(&dir).unwrap_or(dir.clone()).display().to_string(); let (step, visit) = (r.data["currentStep"].as_str().unwrap_or("fields").to_string(), r.data["steps"][r.data["currentStep"].as_str().unwrap_or("fields")]["visits"].as_array().map(|a| a.len()).unwrap_or(1)); // the editor clip of this visit is not the walkthrough: the app window is the camera@@ -4010,7 +4011,9 @@ fn main() { let fields: Value = std::process::Command::new("curl").args(["-s", &format!("http://127.0.0.1:{port}/fields.json")]).output().ok().and_then(|o| serde_json::from_slice(&o.stdout).ok()).unwrap_or(Value::Null); let issues = fields["issues"].as_array().cloned().unwrap_or_default(); r.stage_end("tour-fields", Some(json!({"issues": issues.len(), "tour": tour_ok})), None);- r.outcome("tour-fields", json!({"issues": issues, "nets": fields["nets"], "chips": fields["chips"], "heat": fields["heat"]}));+ if tour_ok {+ r.outcome("tour-fields", json!({"issues": issues, "nets": fields["nets"], "chips": fields["chips"], "heat": fields["heat"]}));+ } r.log("artifact", json!({"step": step, "visit": visit, "kind": "fields-summary", "issues": issues.len(), "peakJ": fields["scales"]["jMax"], "peakRiseC": fields["heat"]["peakRiseC"]})); r.save().unwrap(); if !tour_ok { err("the app's walkthrough did not run (adom-fields tour failed)", &["`adom-fields tour` by hand shows why; the clip of this visit still exists.".into()]); }