These libraries are experimental. APIs may change without notice. Generated from source with koruc 0.1.7 on 10/5/2026.
Winnow
@korulang/winnow@0.0.1Result shaping for agent-facing tool output — per-command grammar of filters, statics, diffs, and judged summaries applied at the tool-result boundary
winnow/index.kz · 7 tors· 4 internal
@korulang/winnow — result shaping for agent-facing tool output · 17 more lines
@korulang/winnow — result shaping for agent-facing tool output
A command runs; something decides what the model actually sees.
Winnow is that decision: a per-command grammar of filters, static
replies, diffs, and judged summaries applied at the tool-result
boundary — inside the scope proc or harness, never wrapped around
a shell.
See DESIGN.md for the full surface and the profiles grammar.
V0 SCOPE — what is here is what works: the tier-1 line ops, pure
string (head / tail / below / dedup) plus the regex trio over
koru/pcre2 (extract.lines / remove.lines / grep — caller hands a bare
pattern, winnow owns the whole-line wrap, compile, and free). The
Myers diff, the koru/ai summarize tier, and the koru/odds escalation
gate are designed in DESIGN.md and land as real lifts, in that order.
Nothing here pretends to a tier it does not implement.
Phantom lifecycles
Derived from the phantom labels in the declarations below — state! issues an
obligation the compiler will chase, !state discharges it, a bare state holds it without moving it. Nothing here is hand-drawn.
String 1 state view!head
index.kz:32// head — first `lines` lines of `text`
//
// Fewer lines than requested returns the whole text. `lines <= 0`
// returns "". Returns a subslice of `text` — no allocation, no copy.
~pub tor head { text: string, lines: i64 } -> stringtail
index.kz:54// tail — last `lines` lines of `text`
//
// Errors live at the end of tool output; this is the single most-used
// op in the profiles grammar. A trailing newline does not mint a
// phantom empty line. Subslice return, no allocation.
~pub tor tail { text: string, lines: i64 } -> stringbelow
index.kz:85// below — everything after the line containing `marker`
//
// The "failing tests:" cut from the profiles grammar: keep what is
// below the marker line, drop the header above it. Marker absent →
// the text unchanged (nothing to cut is an honest answer, not an
// error). Marker on the last line → "".
~pub tor below { text: string, marker: string } -> stringdedup
index.kz:102// dedup — first occurrence wins, order preserved
//
// Progress-bar spam and repeated noise lines collapse to one line
// each. The one allocating op in v0: the output buffer lives on
// page_allocator and is handed back — the produced program's own
// accounting owns the lifetime (same convention as pcre2's error
// messages and odds' transport bodies).
~pub tor dedup { text: string } -> string// remove.lines / extract.lines — the grammar's line filters
//
// Caller hands a BARE pattern; winnow owns wrapping, compiling, and
// freeing the regex. The result is an owned `*String<view!>` the
// caller must `std/string:free`.
~pub tor extract.lines { pattern: string, text: string }
| ok std/string:*String<view!>
| err string~pub tor remove.lines { pattern: string, text: string }
| ok std/string:*String<view!>
| err stringgrep
index.kz:234// grep — does `text` contain a match of `pattern` at all?
~pub tor grep { pattern: string, text: string }
| yes
| no
| err string