build: a model may not lose the submitter's link; uhhm round 7, the mails
Sonnet wrote the ten uhhm mails and replaced the decide link with a
bare {chain}. keep_links puts the fallback's link line back into any
mail that lost it. The mails read easier than the fallbacks (LIX 9 to
33 against 18 to 28) and say something.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
b5f5c46ff2
commit
72a081ed59
+42
-1
@@ -934,6 +934,29 @@ pub fn merge_words(fallback: &Value, given: &Value) -> Value {
|
||||
|
||||
const SLOT: &str = "<WRITE";
|
||||
|
||||
/// A mail's link to the submitter's own move is structure, not
|
||||
/// wording: a model told to keep it still drops it (Sonnet replaced
|
||||
/// the whole line with a bare `{chain}`). Wherever the fallback body
|
||||
/// had a `{site}/decide/…` line and the model's has none, the line is
|
||||
/// put back at the end, and a `{chain}` left on a line of its own is
|
||||
/// removed.
|
||||
fn keep_links(fallback: &Value, merged: &mut Value) {
|
||||
let (Some(fb), Some(mb)) = (fallback.as_object(), merged.as_object_mut()) else { return };
|
||||
for (bucket, stages) in fb {
|
||||
let Some(ms) = mb.get_mut(bucket).and_then(Value::as_object_mut) else { continue };
|
||||
for (stage, spec) in stages.as_object().into_iter().flatten() {
|
||||
let Some(link) = spec["body"].as_str().and_then(|b| b.lines().find(|l| l.contains("{site}/decide/"))) else { continue };
|
||||
let Some(body) = ms.get_mut(stage).and_then(|m| m.get_mut("body")) else { continue };
|
||||
let Some(text) = body.as_str() else { continue };
|
||||
if text.contains("/decide/") {
|
||||
continue;
|
||||
}
|
||||
let kept: Vec<&str> = text.lines().filter(|l| l.trim() != "{chain}").collect();
|
||||
*body = Value::String(format!("{}\n\n{link}", kept.join("\n").trim_end()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The page's wording with every string replaced by a slot that says
|
||||
/// what belongs there. Shown to the model in place of the fallbacks:
|
||||
/// fallbacks read like finished copy, and a small model hands finished
|
||||
@@ -1487,7 +1510,11 @@ pub fn run(argv: &[String]) -> anyhow::Result<()> {
|
||||
std::fs::write(out.join(format!("llm/{:02}-{}.md", n + 1, path.replace('/', "_"))), format!("{prompt}\n\n=== REPLY ===\n{reply}"))?;
|
||||
match first_object(&reply) {
|
||||
Some(given) => {
|
||||
words.insert(path.clone(), merge_words(fallback, &given));
|
||||
let mut merged = merge_words(fallback, &given);
|
||||
if path == "aggregates.yaml" {
|
||||
keep_links(fallback, &mut merged);
|
||||
}
|
||||
words.insert(path.clone(), merged);
|
||||
eprintln!("words: {path}");
|
||||
}
|
||||
None => eprintln!("words: {path} - no usable reply, keeping the fallback"),
|
||||
@@ -1565,6 +1592,20 @@ mod tests {
|
||||
assert!(serde_yaml::from_str::<Plan>(&no_from).unwrap().validate().unwrap_err().to_string().contains("mail: { from"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_models_mail_keeps_the_submitters_link() {
|
||||
let fallback = json!({ "leaks": { "open": { "subject": "s", "body": "Hello,\n\nGot it.\n\nWhat you can do next: {site}/decide/leak?chain={chain}&email={email}\n\nI at i@b.example" } } });
|
||||
let mut merged = json!({ "leaks": { "open": { "subject": "Got it", "body": "Hi,\n\nWe have it.\n\n{chain}" } } });
|
||||
keep_links(&fallback, &mut merged);
|
||||
let body = merged["leaks"]["open"]["body"].as_str().unwrap();
|
||||
assert!(body.ends_with("What you can do next: {site}/decide/leak?chain={chain}&email={email}"));
|
||||
assert!(!body.contains("\n{chain}"));
|
||||
// A body that kept its link is left alone.
|
||||
let mut fine = json!({ "leaks": { "open": { "subject": "s", "body": "Withdraw here: {site}/decide/leak?chain={chain}&email={email}" } } });
|
||||
keep_links(&fallback, &mut fine);
|
||||
assert_eq!(fine["leaks"]["open"]["body"], "Withdraw here: {site}/decide/leak?chain={chain}&email={email}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_live_sites_event_names_survive_a_rebuild() {
|
||||
let mut n = need(&["open", "invited", "active", "departed", "declined"], &["departed", "declined"], &["departed"], &[]);
|
||||
|
||||
Reference in New Issue
Block a user