buildPreview function

String buildPreview(
  1. String body, {
  2. required String spillPath,
  3. required SpillsConfig config,
  4. String? thresholdNote,
})

Builds the symmetric preview for body — exactly what the session stores and the model sees (issue #678 Decision). Pinned sectioning (blank-line separated): header lines / head / omitted marker / tail + read hint:

[spilled: <totalChars> chars, <totalLines> lines (threshold <T> chars)]
[spill file: <spillPath>]

<head — at most headChars, codepoint-safe cut>

[... <omitted> chars omitted ...]

<tail — at most tailChars, codepoint-safe cut>
[read the spill file above for the full output]

Char-bounded (never line-counted — a single giant line stays bounded, AC3), UTF-16 surrogate-pair-safe (AC4), and the omitted marker ([... N chars omitted ...]) carries the TRUE omitted size (AC10). Pure function.

Implementation

String buildPreview(
  String body, {
  required String spillPath,
  required SpillsConfig config,
  String? thresholdNote,
}) {
  final note = thresholdNote ?? 'threshold ${config.threshold} chars';
  // A body the preview bounds already cover renders ONCE — the naive
  // head+tail concat would duplicate it with a negative omitted count
  // (gh-1604: a bench threshold below head+tail bounds must not double
  // the body into the "bounded" preview).
  if (body.length <= config.headChars + config.tailChars) {
    final lines = '\n'.allMatches(body).length + 1;
    return '[spilled: ${body.length} chars, $lines lines ($note)]\n'
        '[spill file: $spillPath]\n'
        '\n'
        '$body\n'
        '$spillReadHint';
  }
  final head = _headExcerpt(body, config.headChars);
  final tail = _tailExcerpt(body, config.tailChars);
  final omitted = body.length - head.length - tail.length;
  final lines = '\n'.allMatches(body).length + 1;
  return '[spilled: ${body.length} chars, $lines lines ($note)]\n'
      '[spill file: $spillPath]\n'
      '\n'
      '$head\n'
      '\n'
      '[... $omitted chars omitted ...]\n'
      '\n'
      '$tail\n'
      '$spillReadHint';
}