{"record":{"id":"a4e1f0045a74464b","repo":"Hmbown/CodeWhale","slug":"continual-harness-field-must-be-min-max-ch","errorCode":null,"errorMessage":"continual harness {field} must be {min}..={max} characters","messagePattern":"continual harness (.+?) must be (.+?)\\.\\.=(.+?) characters","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/tui/src/continual_harness.rs","lineNumber":348,"sourceCode":"            state_path.display()\n        )\n    })?;\n    operation()\n}\n\nfn validate_refinement(mut refinement: HarnessRefinement) -> Result<HarnessRefinement> {\n    refinement.title = normalize_bounded(\"title\", refinement.title, MAX_TITLE_CHARS, 1)?;\n    refinement.content = normalize_bounded(\"content\", refinement.content, MAX_CONTENT_CHARS, 1)?;\n    refinement.evidence =\n        normalize_bounded(\"evidence\", refinement.evidence, MAX_EVIDENCE_CHARS, 16)?;\n    Ok(refinement)\n}\n\nfn normalize_bounded(field: &str, value: String, max: usize, min: usize) -> Result<String> {\n    let value = value.trim().to_string();\n    let len = value.chars().count();\n    if len < min || len > max {\n        bail!(\"continual harness {field} must be {min}..={max} characters\");\n    }\n    Ok(value)\n}\n\nfn truncate_chars(value: &str, max: usize) -> String {\n    let mut chars = value.chars();\n    let head: String = chars.by_ref().take(max).collect();\n    if chars.next().is_some() {\n        format!(\"{head}…\")\n    } else {\n        head\n    }\n}\n\nfn escape_for_prompt(value: &str) -> String {\n    value\n        .replace('&', \"&amp;\")\n        .replace('<', \"&lt;\")","sourceCodeStart":330,"sourceCodeEnd":366,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/0c42157ee52f9d55af2b506d71b46249910f77d3/crates/tui/src/continual_harness.rs#L330-L366","documentation":"Thrown by validate_refinement via normalize_bounded when a refinement field, after trimming, falls outside its character bounds. Limits: title 1..=96, content 1..=1600, evidence 16..=1200 (MAX_*_CHARS constants). Length is counted in Unicode scalar values (chars().count()), and the error names the offending field. Note evidence has a minimum of 16, so a short evidence string like \"test\" fails even though it is non-empty.","triggerScenarios":"Calling refine with an empty title/content, a one-word evidence string under 16 chars, or fields over their maxima (e.g. a 2000-char content).","commonSituations":"The model submitting a refinement with terse evidence; multi-byte text (CJK) where byte length and char count diverge; pasting long briefs into content.","solutions":["Trim or expand the named field to within bounds: title 1-96, content 1-1600, evidence 16-1200 characters","Write evidence of at least 16 characters describing where the refinement was verified","Count characters (not bytes) when pre-measuring CJK content"],"exampleFix":"// before\nlet refinement = HarnessRefinement {\n    kind: HarnessEntryKind::PromptNote,\n    title: \"note\".into(),\n    content: \"Use release builds for timing.\".into(),\n    evidence: \"test\".into(),\n};\n\n// after\nlet refinement = HarnessRefinement {\n    kind: HarnessEntryKind::PromptNote,\n    title: \"note\".into(),\n    content: \"Use release builds for timing.\".into(),\n    evidence: \"Verified on the dxg repo: release build reproduced the 2x speedup.\".into(),\n};","handlingStrategy":"validation","validationCode":"fn refinement_is_valid(r: &HarnessRefinement) -> bool {\n    let in_bounds = |v: &str, min: usize, max: usize| {\n        let n = v.trim().chars().count();\n        (min..=max).contains(&n)\n    };\n    in_bounds(&r.title, 1, 96)\n        && in_bounds(&r.content, 1, 1600)\n        && in_bounds(&r.evidence, 16, 1200)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Remember evidence needs at least 16 characters; a token like \"test\" is rejected","Measure with chars().count() (Unicode scalars), not bytes, especially for CJK text","Validate in the tool layer before calling refine so users get field-specific feedback"],"tags":["rust","tui","harness","validation","string-length"],"backgroundTag":"string-length-validation","analyzedSha":"0c42157ee52f9d55af2b506d71b46249910f77d3","analyzedAt":"2026-08-20T21:50:45.477Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}