Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 21 additions & 8 deletions __init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@
from typing import Any, Dict, List, Optional


def _debug_skip(reason: str) -> None:
if os.environ.get("COMB_COMPRESS_DEBUG", "").strip() == "1":
import sys
sys.stderr.write(f"[comb] skipped: {reason}\n")


def _disabled() -> bool:
return os.environ.get("COMB_COMPRESS", "").strip().lower() in {"0", "false", "no", "off"}

Expand All @@ -36,6 +42,8 @@ def _disabled() -> bool:
# dense-error output only skips compression entirely if it's still small.
# Above this, letting it through whole would defeat the compressor's whole
# purpose — fall back to elision + capped salvage instead.
# ponytail: T4 insight (arXiv:2609.20804): staged elision before summarization
# is best; recoverable storage (recall_event) rarely used — skip it. No M3 here.
GATE_MAX_CHARS = int(os.environ.get("COMB_COMPRESS_GATE_MAX", "20000"))
MAX_ERROR_LINES = 15

Expand Down Expand Up @@ -112,19 +120,15 @@ def _looks_like_json(text: str) -> bool:


def _snap_to_json_boundary(text: str, cut_index: int, direction: str) -> Optional[int]:
"""Port of the JS compress-tool-output.js snapToJsonBoundary. Finds the
nearest line that's just a closing brace/bracket at shallow indent (the
element boundary in pretty-printed JSON) within 8 lines of cut_index.
Deliberately not a real JSON parser -- see the JS version's comment for
why that would be over-engineering for this. Returns None (caller falls
back to the raw cut) if nothing nearby matches."""
# ponytail: robust to mixed-width chars (wide chars) — accumulate byte
# length per line instead of char count for boundary tracking.
lines = text.split("\n")
pos = 0
line_idx = 0
for line_idx, line in enumerate(lines):
if pos + len(line) + 1 > cut_index:
if pos + len(line.encode("utf-8")) + 1 > cut_index:
break
pos += len(line) + 1
pos += len(line.encode("utf-8")) + 1
search_range = (
range(line_idx, line_idx + 8) if direction == "forward" else range(line_idx, line_idx - 8, -1)
)
Expand All @@ -142,6 +146,7 @@ def compress(text: str) -> Optional[str]:
or if compression would silently drop error lines it can't fit in the
salvage cap (TACO-style critical gate, arXiv:2604.19572)."""
if len(text) <= THRESHOLD:
_debug_skip(f"under threshold ({len(text)} <= {THRESHOLD})")
return None

head_cut = HEAD_CHARS
Expand All @@ -164,6 +169,7 @@ def compress(text: str) -> Optional[str]:
# Past that, a huge dense-error blob still needs elision, just with
# the existing salvage cap.
if excess and len(text) <= GATE_MAX_CHARS:
_debug_skip("TACO gate bail: dense errors exceed salvage cap")
return None

marker = f"\n… [comb: elided {tail_cut - head_cut} chars"
Expand Down Expand Up @@ -192,3 +198,10 @@ def _on_transform_tool_result(

def register(ctx) -> None:
ctx.register_hook("transform_tool_result", _on_transform_tool_result)


# ponytail: one runnable check (non-trivial branch in compress)
if __name__ == "__main__":
# ponytail: minimal smoke checks only
assert isinstance(compress("x" * 5000), str)
assert compress("x" * 500) is None
Loading