Skip to content

feat(k8s): cache-aware kubectl pods/services + impact-scored discover - #3725

Open
wussh wants to merge 1 commit into
rtk-ai:developfrom
wussh:feat/kubectl-pods-cache
Open

feat(k8s): cache-aware kubectl pods/services + impact-scored discover#3725
wussh wants to merge 1 commit into
rtk-ai:developfrom
wussh:feat/kubectl-pods-cache

Conversation

@wussh

@wussh wussh commented Aug 27, 2026

Copy link
Copy Markdown

Problem

In real-world agent usage, kubectl get pods is by far the largest single token sink — 16,092 calls / ~90.7M tokens saved over 30 days in my own history. But the existing format_kubectl_pods filter already compresses aggressively (counts + capped issue list). The filter isn't the gap; call frequency is. An agent polling a stable cluster gets the same summary re-sent dozens of times in a row.

Separately, rtk discover's "TOP UNHANDLED COMMANDS" table sorts by raw call count, so a rare-but-huge command is buried under a frequent tiny one — no signal about which is actually worth filing an issue for.

Changes

Two independent, separately-reviewable changes:

1. Result-diff caching for kubectl/oc get pods/services (src/core/k8s_cache.rs)

Hashes the already-filtered summary text (not raw JSON) keyed by tool+resource+args. When a repeat call produces an identical summary within a 15s sliding poll-gap window, output collapses to one line instead of the full summary. --force bypasses it.

Hashing post-filter output rather than raw JSON sidesteps normalizing volatile fields (resourceVersion, managedFields, timestamps) out of an open-ended schema — those never surface in the summary by construction.

2. Impact-scored rtk discover (src/discover/)

Adds impact = call_frequency × avg_output_tokens_for_category and a Priority column, replacing the raw-count sort on the unhandled-commands table. Reuses the existing category_avg_tokens table via a new guess_unsupported_category helper, so unhandled commands get the same per-category estimate as handled ones.

Design philosophy compliance

  • Correctness vs Token Savings — the real kubectl/oc command still executes on every call; only the re-printing of an unchanged result is skipped, never the query itself. Stale cluster state shown to an agent debugging a live rollout would be far worse than the token cost. --force is the flag-aware escape hatch for explicitly-requested full detail.
  • Transparency — collapsed output retains the real count line (7 pods: 7) and names its own escape hatch. No new format for the normal (uncached) path.
  • Never Block — every cache path is failure-tolerant: unreadable/corrupt cache file, missing data dir, and serialization failures all degrade to a normal full summary rather than erroring.
  • Zero Overhead — one small local JSON read/write, no network. Timing against a live cluster is dominated by the kubectl call itself (~900ms–1s); cache overhead is not measurable against it.
  • Extensibility — reuses never_worse via the existing runner::run_filtered path, the dirs::data_local_dir()/RTK_DATA_DIR storage convention from core/tracking.rs, and discover's existing category tables. No new storage layer, no new UI concept.

Testing

  • 6 new unit tests in k8s_cache.rs (first call, unchanged repeat, changed state, --force, flag extraction)
  • Full suite green: 2734 tests, 0 failures. cargo clippy --all-targets clean, cargo fmt --check clean.
  • Manual verification against a live cluster:
    $ rtk kubectl pods -n argocd
    7 pods: 7
    $ rtk kubectl pods -n argocd
    No material change since previous query (1s ago). 7 pods: 7
    Use --force for fresh detail.
    $ rtk kubectl pods -n argocd --force
    7 pods: 7
    
  • rtk discover --all against 275 real sessions / 13,091 commands — new Priority column reorders the unhandled table sensibly.

Notes / out of scope

  • No new filters for the unhandled commands the improved discover now surfaces (sshpass, python3, export, …) — happy to file those as separate issues per the contribution norms.
  • --force is added only to the kubectl pods/services shorthand subcommands, not oc — the oc variants pass false and behave exactly as before.
  • A pre-existing unrelated limitation surfaced during testing: kubectl get pods -A on a large cluster exceeds the 10 MiB filter-input cap and falls back to raw. Not touched here; mentioning in case it's of interest.
kubectl get pods/services is the single biggest token sink (90.7M
tokens over 16K calls in real usage) — the existing JSON-summary
filter already compresses aggressively, so the actual gap is call
frequency, not filter quality.

- Cache the hash of the already-filtered summary (not raw JSON, so
  volatile fields like resourceVersion never matter). Repeated polls
  of unchanged cluster state collapse to one line within a 15s
  sliding TTL window; --force bypasses for guaranteed fresh detail.
  Still runs the real kubectl/oc call every time — never skips the
  query itself.
- discover's "TOP UNHANDLED COMMANDS" list was sorted by raw call
  count only. Add an impact score (count x avg output tokens for a
  guessed category) and a Priority column so a rare-but-huge command
  isn't buried under a frequent tiny one.

Verified: cargo test (full suite green), manual run against a live
cluster (tbs-dev) confirming collapse/--force/services behavior, and
discover against this repo's own 30-day session history.
@CLAassistant

CLAassistant commented Aug 27, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

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

Labels

None yet

2 participants