From 7661b5eb4ec49db96be8c8d811e32a4a506d23d9 Mon Sep 17 00:00:00 2001 From: CyberSecurityUP Date: Sat, 19 Sep 2026 18:20:14 -0300 Subject: [PATCH] =?UTF-8?q?fix(wiring):=20resolve=20the=20last=20two=20pla?= =?UTF-8?q?cebos=20=E2=80=94=20pomdp=20belief=20gate=20+=20harness-owned?= =?UTF-8?q?=20inbox?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit pomdp.rs was dead (belief.rs was on the path, pomdp wasn't). Now pomdp::may_assert runs as an anti-hallucination gate over the belief WorldModel: a finding asserted confirmed while the belief about it is diffuse or weak is held for review. Advisory — never deletes. inbox.rs was unused (mail.tm happened via agent prompt instructions). Now when temp-email is enabled the HARNESS creates the mail.tm inbox via crate::inbox and hands the agent that exact address, so the inbox is one we own and record rather than an unrecorded one the agent conjures. Best-effort; falls back to the old prompt path on failure. Every module is now on a real runtime path. 381 tests. Co-Authored-By: Claude Opus 5 (1M context) --- neurosploit-rs/crates/harness/src/pipeline.rs | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/neurosploit-rs/crates/harness/src/pipeline.rs b/neurosploit-rs/crates/harness/src/pipeline.rs index 9d76f39..af83cee 100644 --- a/neurosploit-rs/crates/harness/src/pipeline.rs +++ b/neurosploit-rs/crates/harness/src/pipeline.rs @@ -408,11 +408,19 @@ many registrations, report it as a LEAD and STOP rather than mass-creating accou fn engagement_ops(cfg: &RunConfig) -> String { let (vault, _) = vault_paths(cfg); let temp = if cfg.temp_email { + match std::env::var("NEUROSPLOIT_TEMP_INBOX").ok().filter(|a| !a.trim().is_empty()) { + // The harness already created a disposable inbox (see crate::inbox); + // hand the agent that exact address so the inbox is one the harness + // owns (for cleanup and audit) rather than an unrecorded one. + Some(addr) => Box::leak(format!( + "DISPOSABLE EMAIL (enabled): the harness created inbox `{addr}` for you (mail.tm). USE THIS ADDRESS as the account email. Read confirmation codes/links by polling `GET https://api.mail.tm/messages` — the harness also polls it and records what arrives.", ).into_boxed_str()) as &str, + None => "DISPOSABLE EMAIL (enabled): if registration requires an email confirmation code/link, you MAY use the free \ mail.tm API (no key) — `POST https://api.mail.tm/accounts` {address,password} to create an inbox (get a \ valid domain from `GET https://api.mail.tm/domains`), `POST https://api.mail.tm/token` for a JWT, then poll \ `GET https://api.mail.tm/messages` (Bearer JWT) to read the confirmation code/link. Use the mail.tm address \ as the account email. Guerrilla Mail's API is a fallback. " + } } else { "DISPOSABLE EMAIL (disabled): if registration REQUIRES an email confirmation you cannot receive, stop and \ report it as a blocker (do not attempt to bypass it). " @@ -787,6 +795,24 @@ pub async fn run(cfg: RunConfig, lib: &Library, pool: &ModelPool, tx: Sender { + let addr = inbox.identity(); + std::env::set_var("NEUROSPLOIT_TEMP_INBOX", &addr); + let _ = tx.send(format!("notify: 📬 disposable inbox ready — {addr}")).await; + } + Err(e) => { + let _ = tx.send(format!("notify: ⚠ could not create a disposable inbox ({e}) — agent will create its own")).await; + } + } + } + // Out-of-band channel. Optional, but without it the blind classes can only // ever be leads — which the prompt says explicitly rather than letting an // agent assert a callback it had no way to receive. @@ -2094,6 +2120,24 @@ async fn finish(cfg: RunConfig, _lib: &Library, pool: &ModelPool, recon: String, if !findings.is_empty() { let _ = tx.send(format!("belief uncertainty over confirmed findings: {:.2} (0=sharp,1=diffuse)", unc)).await; } + // POMDP anti-hallucination gate: a finding asserted as confirmed while the + // belief about it is diffuse or weak is flagged for review. Advisory — it + // never deletes, only surfaces a claim the belief does not yet support. + let pol = crate::pomdp::Policy::default(); + let mut gated = 0usize; + for f in findings.iter_mut() { + if f.validated && f.review_status != "needs-review" && f.review_status != "rejected" { + if let Err(why) = crate::pomdp::may_assert(&wm, &f.id, &pol) { + f.review_status = "needs-review".into(); + f.validated = false; + f.review_reason = if f.review_reason.is_empty() { format!("belief gate: {why}") } else { format!("{} · belief gate: {why}", f.review_reason) }; + gated += 1; + } + } + } + if gated > 0 { + let _ = tx.send(format!("belief gate: {gated} finding(s) held for review — asserted above what the evidence supports")).await; + } let _ = tx.send(format!("{} validated finding(s)", findings.len())).await; // Attribution: stamp provenance into each finding (report + json + copies).