Skip to content

feat(harness): deterministic resolve → status display → runtime wiring (#2693)#4293

Open
SamhandsomeLee wants to merge 9 commits into
Hmbown:mainfrom
SamhandsomeLee:codex/2693-tool-surface
Open

feat(harness): deterministic resolve → status display → runtime wiring (#2693)#4293
SamhandsomeLee wants to merge 9 commits into
Hmbown:mainfrom
SamhandsomeLee:codex/2693-tool-surface

Conversation

@SamhandsomeLee

Copy link
Copy Markdown
Contributor

Summary

Implements #2693 as one reviewable stack on latest main: deterministic harness resolution, read-only status surfaces, then runtime wiring for compaction / sub-agent concurrency / tool surface.

Slice map

Slice What landed
PR1 Deterministic resolve_harness (specificity + user-over-builtin + stable tiebreak; default Standard when unmatched). Old resolve_harness_profile kept.
PR2 Read-only /harness status + footer posture chip (preview only; drops first under width pressure).
PR3-0 Cache HarnessResolution on the session and inject posture into EngineConfig (carry path for later consumers).
PR3a Wire compaction_strategy into compaction timing + protected window (Default identity; PrefixCache later/wider; Aggressive earlier).
PR3b Wire max_subagents into runtime concurrency (posture when > 0; explicit CLI --max-subagents wins via max_subagents_cli_override; live sync on model/config changes).
PR3c Wire tool_surface into catalog/registry (never widens); ReadOnly filters + execution-time denial; ensure_advanced_tooling does not re-add exec tools under ReadOnly.

Non-goals / hard boundaries

  • No auth, base URL, model-id, permission, or provider-routing writes.
  • tool_surface only narrows; Full/Auto are no-ops relative to the existing catalog.
  • Standard / Default paths stay byte-identical where claimed (especially compaction Default).

Commits (onto current main)

  1. fix(tui): anchor compaction trigger to the input budget ceiling
  2. feat(config): add deterministic harness profile resolver
  3. feat(tui): add read-only harness status display
  4. feat(tui): carry harness resolution on session
  5. feat(tui): wire harness compaction strategy into compaction (#2693 PR3a)
  6. feat(tui): wire harness max_subagents into runtime concurrency (#2693 PR3b)
  7. feat(tui): wire harness tool_surface into catalog (never widens) (#2693 PR3c)
  8. fix(tui): fill max_subagents_cli_override in TuiOptions after rebase

Evidence (PR3a)

Method. Same interactive workload twice on deepseek-v4-flash (YOLO) with auto_compact_threshold_percent = 10. PrefixCache arm = built-in CacheHeavy seed for deepseek-v4*; Default arm forced via user [[harness_profiles]] (kind = standard, compaction_strategy = default). Metrics from /cache stats and /status.

Metric Default PrefixCache (timing+path)
Session prompt-cache hit rate 90.8% 94.6%
Prefix stability 95% (4 changes) 98% (2 changes)
Cache-miss tokens 637.8K 430.5K
Total input processed 7.0M 8.0M
Session cost ¥0.9012 ¥0.7422
Turns recorded 15 16

Result. Cache-heavy posture kept the pinned prefix more stable (2 vs 4 rewrites), raised session prompt-cache hit rate 90.8% → 94.6%, and cut cache-miss tokens ~32%. Even with more input processed (8.0M vs 7.0M), cost was lower (¥0.74 vs ¥0.90).

Deterministic lever check (base 80% on deepseek-v4-pro): PrefixCache raises trigger 589,466 → 648,412 tokens and widens protected window 4 → 8; Aggressive lowers to 501,046; Default is byte-for-byte identity (589,466 / window 4).

Caveats. One run per arm (directional, not exact). Compaction count proxied by prefix-change count on Windows (tracing logs not flushed; compaction summary call: unavailable). timing-only vs timing+path not split; numbers above are timing+path.

Testing

  • cargo fmt (local; rebased branch)
  • cargo fmt --all -- --check
  • cargo clippy --workspace --all-targets --all-features
  • cargo test --workspace --all-features
  • Targeted: cargo test -p codewhale-tui --bin codewhale-tui --locked harness_18 passed (after rebase onto latest main)
  • Targeted: cargo test -p codewhale-config (resolver suite; please re-run in CI / before merge)

Checklist

  • Updated docs or comments as needed (inline docs on resolver / posture carry / never-widens tool surface)
  • Added or updated tests where relevant (resolver, /harness, posture refresh, max_subagents CLI pin, tool_surface filter/deny)
  • Verified TUI behavior manually if UI changes (/harness, footer posture chip; PR3a interactive evidence above)
  • Harvested/co-authored credit uses a GitHub numeric noreply address (N/A — original work by @Samhandsome; no harvest / no bot Co-authored-by)

The compaction trigger was computed as a percentage of the raw context
window in every live path, ignoring the output tokens reserved for the
turn. The window is the wrong denominator: input can only ever occupy
`window - reserved_output - headroom` (the input budget ceiling), so a
percentage of the window can sit above the room input can actually use.

Symptoms this fixes:

- Tight self-hosted windows (e.g. a 256K vLLM deployment reserving a
  large output cap) put the 80% trigger above the usable ceiling, so
  automatic compaction fired too late - the session ran until the
  provider hard-rejected on context length.
- Even V4's 1M window reserves 262K for interleaved thinking, so the old
  80%-of-window trigger (800K) sat above the ~736K input can hold.
- `ContextBudget` already computed the correct ceiling but then derived
  its `compaction_trigger_tokens` from the window, and that field was
  never wired to the live trigger at all - the live thresholds lived in
  three separate `percent * window` sites instead.

Changes:

- `ContextBudget` is now the single source of the trigger formula: it
  exposes `input_budget_ceiling` and `compaction_trigger_for_percent`,
  and its default trigger field is anchored to the ceiling. Because the
  percentage is applied to the ceiling (and clamped to <=100%), the
  trigger can never exceed the ceiling by construction.
- `route_budget`'s route and model trigger helpers build a
  `ContextBudget` and read the ceiling-anchored trigger; no caller
  computes its own `percent * window` anymore.
- The TUI pre-send auto-compact gate compares estimated context against
  the shared `compact_threshold` (ceiling-derived) instead of a
  window-relative percentage, keeping it in the same dimension as the
  engine auto-compaction.
- Moved the output-reservation primitives (`TURN_MAX_OUTPUT_TOKENS`,
  `effective_max_output_tokens`, `route_output_reservation_for_window`)
  from `core/engine/context.rs` down to `route_budget` so the trigger
  helpers can reserve output without an upward dependency into the
  engine; the engine re-exports `effective_max_output_tokens`.
- Moved `compaction_threshold_for_model_at_percent` from `models` to
  `route_budget` for the same reason; `models` stays dependency-free so
  the `#[path]`-included integration harness still compiles.

Behavior change (this is the bugfix, not a regression): with output
reserved before measuring fullness, the Default trigger moves earlier on
every route. At 80%, deepseek-v4-pro drops 800_000 -> 589_466 and a 256K
trinity route drops 209_715 -> 156_467. Auto-compact enable/disable
defaults are unchanged.

Tests: a deterministic property test sweeps a wide grid of
window/output-cap/input/percent and asserts trigger <= ceiling, making
the overflow impossible by construction rather than clamped away.
Migration tests cover the large-window (V4) and tight-window cases, and
the existing engine input-budget tests confirm the reservation math is
preserved.
Make HarnessProfile resolution order-independent with provenance and a Standard fallback. Adds resolve_harness, which ranks user profiles ahead of built-in seeds by model_pattern specificity. Pure config logic only; no runtime behavior change (Hmbown#2693).
Add /harness command and a footer posture chip that show the resolved harness posture, its source, and repo-law path separately. Consumes resolve_harness from PR1; preview-only with no runtime behavior change (Hmbown#2693).
Cache resolved HarnessResolution on App and inject posture into EngineConfig for TUI, exec, and runtime-thread paths. Zero runtime consumption until PR3a; adds refresh hooks, Default on HarnessResolution, and tests.
 PR3a)

PrefixCache compacts later via posture-adjusted trigger percent and protects a wider recent-message window; Aggressive compacts earlier; Default stays unchanged on both levers. should_compact comparison logic is untouched.

Also update the /harness panel copy now that the compaction strategy is consumed at runtime: the header no longer claims the posture is inert (was 'preview - does not change runtime behavior yet') and the compaction row is marked (live). Other knobs (max_subagents/tool_surface/safety) remain preview.
…n#2693 PR3b)

When posture.max_subagents > 0, use it as the default concurrent sub-agent
cap (still clamped to MAX_SUBAGENTS). Zero keeps the config path
byte-identical. Explicit CLI --max-subagents wins via a dedicated override
flag, and model/config changes sync the live engine through
SetSubagentRuntimeConfig so App and engine stay aligned.
…own#2693 PR3c)

ReadOnly intersects the Mode-built registry and MCP list with read-only
tools only; Full/Auto stay no-ops. Execution denies non-read-only calls,
and ensure_advanced_tooling skips code_execution/js_execution under
ReadOnly so the model-visible catalog cannot re-widen after filtering.
New main-side test helpers lacked the PR3b field and failed to compile.
@SamhandsomeLee SamhandsomeLee requested a review from Hmbown as a code owner July 9, 2026 08:05
@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown

Thanks @SamhandsomeLee for taking the time to contribute.

This repository is observing a maintainer-managed PR intake gate in dry-run mode, so this pull request is staying open. This note helps maintainers prepare the allowlist before any enforcement is considered.

Please read CONTRIBUTING.md for the expected contribution shape. A maintainer can grant recurring PR access by commenting /lgtm on a pull request.

Hmbown commented Jul 9, 2026

Copy link
Copy Markdown
Owner

wow cool! let me check this out and work to get it in this version. thank you for your hard work on this!

@SamhandsomeLee

Copy link
Copy Markdown
Contributor Author

哇,太棒了!我这就去看看,争取把它加到这个版本里。感谢你为此付出的辛勤努力!

Thank you! I'm glad it looks useful. This is my CodeWhale contribution, and I’m happy to help refine it or adjust anything needed so it can fit well into this version.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants