Strip C0/C1 control characters and DEL from model/diff-derived strings
before printing to the terminal, preventing OSC 52 clipboard hijack,
screen erasure spoofing, and other ANSI injection attacks (CWE-150).
JSON output is unaffected as encoding/json already escapes control chars.
- Replace hardcoded fmt.Printf width specifiers with text/tabwriter
- Column widths now adapt to actual content, preventing overflow
- Eliminates risk of misaligned columns when provider names exceed preset width
The cpAuth text input width was 40, which truncated the 51-character
placeholder "optional, leave empty for default (Authorization)".
Increased to 55 so the full text is visible.
Previously --max-tools only took effect when greater than the template
default (30), making it impossible to reduce iterations for large diffs.
Now any non-zero value overrides the default, clamped to a floor of 10
with a stderr warning when the input is below the minimum.
Export NormalizeAuthHeader from the llm package and remove the duplicate
normalizeConfigAuthHeader in config_cmd.go. Invalid auth_header values
now return an error at configuration time instead of being silently
accepted and causing opaque 401s at runtime.
Subtask errors are already printed in real-time when they occur in agent.go.
The final outputTextWithWarnings was printing them again after comments were displayed.
Introduce gitcmd.Runner with channel-based semaphore to cap concurrent
git subprocesses (default 16, configurable via --max-git-procs). Route
all tool-layer and diff-layer git calls through the shared runner.
Also fix diff.Provider.runGit lacking context.Context — now the full
chain (GetDiff → MergeBase → ParseDiffText → finalizeDiff) propagates
the caller's context for proper cancellation and timeout support.
Registry was a plain map alias and DiffMap a shared map[string]string,
both relying on implicit write-before-read ordering with no compile-time
safety. Refactor Registry into an encapsulated struct with Freeze() that
panics on post-freeze writes, and wrap DiffMap as an immutable value type
with defensive copy on construction. Move DiffMap injection to before
filterDiffs to preserve the original behavior of exposing all file diffs.
Add cache_control ephemeral breakpoints on system prompt and tool
definitions to activate Anthropic prompt caching for multi-turn
agent loops. Fix token double-counting by removing the redundant
totalTokensUsed accumulator and computing it from sub-items. Surface
cache read/write statistics in both text and JSON summary output.
When using --audience agent --format json, the text summary line was
printed before the JSON body, causing parse failures for integrations.
Move summary data into the JSON "summary" field and skip PrintTraceSummary
in JSON mode.
Unify the config folder name to `.opencodereview` across all runtime paths,
tests, docs, and i18n strings. Also make defaultConfigPath() return an error
instead of silently falling back to a current-directory file when $HOME is
unresolvable.
Allow users to configure include/exclude glob patterns in
.open-code-review/rule.json (global or project-level) to control
which files are reviewed. Exclude has highest priority, include
penetrates default path exclusions but not the extension allowlist.
Only one layer takes effect following --rule > project > global priority.
Consolidate review rules into a composedResolver that supports four layers
(--rule flag > project .open-code-review/rule.json > global ~/rule.json >
embedded system default), each with first-match-wins fall-through semantics.
When all subtask LLM calls fail (e.g. invalid API key), dispatchSubtasks
now returns an error instead of empty comments with nil error. Partial
failures are recorded as subtask_error warnings so output functions can
distinguish "no issues found" from "review failed".