── Tool-output regression suite (gating) ────────────────────────── * Context-explosion detector: flags the measured smells that re-introduce * token bloat into default outputs, independent of any specific tool: * 1. blocked internal fields (fp/sp/bt) appearing anywhere; * 2. repeated-key JSON envelopes — the same key emitted per row instead of * a header-once table (the un-TOONed en
| 2353 | * belongs in tool descriptions or docs, not repeated per response. |
| 2354 | * Returns NULL when clean, else a static description of the violation. */ |
| 2355 | static const char *output_explosion_smell(const char *inner) { |
| 2356 | static const char *row_keys[] = { |
| 2357 | "\"name\":", "\"label\":", "\"file\":", "\"path\":", "\"qualified_name\":", "\"qn\":"}; |
| 2358 | if (strstr(inner, "\"fp\":") || strstr(inner, "\"sp\":") || strstr(inner, "\"bt\":")) { |
| 2359 | return "blocked internal field (fp/sp/bt) leaked into output"; |
| 2360 | } |
| 2361 | for (size_t k = 0; k < sizeof(row_keys) / sizeof(row_keys[0]); k++) { |
| 2362 | int n = 0; |
| 2363 | for (const char *p = strstr(inner, row_keys[k]); p && n <= 32; |
| 2364 | p = strstr(p + 1, row_keys[k])) { |
| 2365 | n++; |
| 2366 | } |
| 2367 | if (n > 32) { |
| 2368 | return "repeated-key envelope (>32x same JSON key) — emit a header-once table"; |
| 2369 | } |
| 2370 | } |
| 2371 | for (const char *p = strstr(inner, "\"note\":\""); p; p = strstr(p + 1, "\"note\":\"")) { |
| 2372 | const char *end = strchr(p + 9, '"'); |
| 2373 | while (end && end[-1] == '\\') { |
| 2374 | end = strchr(end + 1, '"'); |
| 2375 | } |
| 2376 | if (end && end - (p + 9) > 220) { |
| 2377 | return "embedded note exceeds one line (~220 chars)"; |
| 2378 | } |
| 2379 | } |
| 2380 | return NULL; |
| 2381 | } |
| 2382 | |
| 2383 | /* Run one tool call on the fixture server, apply the explosion detector and |
| 2384 | * an absolute byte ceiling, and require a semantic-floor marker so trimming |