Skip to content

Next Release#1879

Merged
aeppling merged 39 commits into
masterfrom
develop
May 22, 2026
Merged

Next Release#1879
aeppling merged 39 commits into
masterfrom
develop

Conversation

@aeppling
Copy link
Copy Markdown
Contributor

@aeppling aeppling commented May 13, 2026

ousamabenyounes and others added 6 commits April 17, 2026 15:55
…1250)

The installer previously ran `tar -xzf` on the downloaded archive with no
pre-extraction verification. A malicious mirror could ship a tarball with
`../` components or absolute paths and write files anywhere on the user's
filesystem (CWE-22).

Add a pre-extraction check that lists archive contents with `tar -tzf`
and rejects any entry whose name starts with `/` or contains a `..` path
component. The check is POSIX-compliant and adds negligible overhead for
the single-binary RTK release tarball.

Covered by scripts/test-install.sh, which exercises one safe archive
and four crafted malicious archives (leading `..`, absolute path,
mid-path `..`, trailing `..`) plus a regression guard that ensures the
check remains in install.sh.

Co-Authored-By: Claude <noreply@anthropic.com>
fix(install): reject archive with path traversal before extraction (#1250)
fix(git): preserve full status paths and untracked files
Previously `rtk docker compose logs --tail=20 web` would fall through to
the passthrough handler because clap had no `--tail` field on the `Logs`
subcommand, resulting in 0% token savings. Additionally, `run_compose_logs`
always fetched 100 lines regardless of user input.

- Add `#[arg(long, default_value_t = 100)] tail: u32` to `ComposeCommands::Logs`
- Thread the value through to the docker invocation
- Default unchanged (100 lines), so bare `rtk docker compose logs` behaves as before

Ports the core fix from #580, retargeted onto current develop layout
(`src/cmds/cloud/container.rs`). Relates to #578.

Co-authored-by: Mihir Dash <137862945+slice-mihird@users.noreply.github.com>
fix(docker): forward --tail flag in compose logs
@CLAassistant
Copy link
Copy Markdown

CLAassistant commented May 14, 2026

CLA assistant check
All committers have signed the CLA.

aeppling and others added 23 commits May 15, 2026 19:12
…iltering

Several filters dropped or rewrote information an agent needs, producing
output that was misleading rather than merely compressed. This fixes the
clear-cut cases surfaced by the TheDecipherist/rtk-test suite:

- ls: stop hiding the `.env` file (removed `.env`/`env` from NOISE_DIRS).
- git status: restore the explicit "HEAD detached at <sha>" line instead of
  the opaque "* HEAD (no branch)".
- log/docker logs: recognise CRITICAL/FATAL/ALERT/EMERGENCY/SEVERE (and
  NOTICE) as severities so those lines are no longer silently filtered;
  expose `log` as a `rtk pipe` filter and accept a positional filter name.
- wc: forward stdin to the child so `cat file | rtk wc` counts the pipe
  instead of reporting 0 (new RunOptions::inherit_stdin).
- jest/vitest: include skipped/pending test count in the compact summary.
- pytest: surface xfailed/xpassed counts and list XFAIL/XPASS entries with
  their reasons (adds `-rxX`).
- ruff/eslint: list individual violations with file:line:col, not just
  rule/file group counts.
- pnpm/npm list: render the actual package list instead of the false-positive
  "All packages up-to-date" when there's no upgrade info.
- git add: stay silent on a no-op instead of printing an ambiguous "ok".
- git stash: pass git's own message through instead of collapsing to "ok".
- docker ps: keep the Status column (health/restart info) and list
  stopped/exited containers; docker images: show all images with full names;
  docker compose ps: use `-a` so crashed services stay visible.

All 1870 unit tests pass; cargo fmt + clippy clean.
## Problem (#963)

`rtk git push` reportedly times out: users see
`bash tool terminated command after exceeding timeout 30000 ms` while
plain `git push` to the same remote completes fine. P1-critical because
every Claude Code git push goes through rtk.

## Root cause

`run_push` used `cmd.stdin(Stdio::inherit()).output()`. `Command::output()`
captures both stdout and stderr until the child exits. Git push prints
its progress (`Counting objects` / `Compressing objects` / `Writing
objects`) to stderr and may prompt for SSH passphrases or HTTPS
credentials. With stderr captured, Claude Code's bash tool saw zero
output for 30+ seconds and killed the command — exactly the 30000 ms
message in the issue.

## Fix

Rewrite `run_push` on top of the streaming infrastructure that already
exists for this exact purpose (`stream::run_streaming` +
`FilterMode::Streaming`, added in 0.37.0).

Add a counterpart to `BlockStreamFilter<H: BlockHandler>` in
`src/core/stream.rs`: `LineStreamFilter<H: LineHandler>`. Where
`BlockStreamFilter` defaults to DROP and emits only collected blocks,
`LineStreamFilter` defaults to KEEP and lets handlers opt into dropping
noise. Trait surface mirrors `BlockHandler`:

- `should_skip(&mut self, line: &str) -> bool` — default false
- `observe_line(&mut self, line: &str)` — default no-op
- `format_summary(&self, exit_code, raw) -> Option<String>`

This lets future streaming commands reuse the line-oriented pattern.

`GitPushLineHandler` then becomes a tiny `LineHandler` impl:

- `should_skip` drops the high-volume progress phases (Enumerating /
  Counting / Compressing / Writing objects, Delta compression, Total)
  and blank lines.
- `observe_line` captures the up-to-date sentinel and the first ref
  update target (e.g. `master`) for the summary.
- `format_summary` emits `ok <ref>` / `ok (up-to-date)` / `ok` on
  success; nothing on failure (raw error lines already flowed through).

Stdin is inherited (`StdinMode::Inherit`) so SSH passphrase and HTTPS
credential prompts still reach the user. Tracking now records the real
raw output and the filtered output.

## Test plan

- [x] `cargo fmt --all -- --check`
- [x] `cargo clippy --all-targets -- -D warnings` — clean
- [x] `cargo test --all` — 1880 passed, 0 failed, 6 ignored
- Six unit tests cover the push handler: progress-prefix drop,
  up-to-date summary, remote message passthrough, no-summary-on-failure,
  first-ref-wins, and token-savings (>=60% on a representative payload).
- Four unit tests cover the new `LineStreamFilter` trait:
  default-keep-all, skip-drops-matching, summary-propagates-exit-code,
  observe-only-called-for-kept-lines.

## Notes

- Behaviour change: users now see git's native output line-by-line
  (with progress phases stripped) plus a final `ok <ref>` summary,
  instead of just the compact summary. This matches plain `git push`
  more closely and is what the issue reporter expects.
- No regression for other filters: `run_pull`, `run_fetch`, `run_clone`
  are untouched; only `run_push` is modified.

Closes #963

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---
_Vibe Coded by Ousama Ben Younes_
_Developed With Ora Studio (Claude Code)_

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- fix signal truncation gaps + kush reviews
- added a new tee and hints function to give an hint with tail (avoid re-ingest of the head)
- extracted patterns in constants
Co-authored-by: Cursor <cursoragent@cursor.com>
fix(kubectl): compact get pods and services aliases
fix(git): stream push output to avoid spurious 30s timeout (#963)
- docker ps reverts to plain (no -a augmentation)
- docker ps -a / compose ps -a wired to the running/stopped split filter
- ruff Violations: capped at 50 + force_tee_tail_hint recovery
- tests for the ruff and pytest xfail caps
Replace all bare magic offset literals (e.g. 21 for cap=20) with named
constants (MAX_XXX + 1) so offsets stay in sync if caps change.
Fix compose_ps to tee pre-formatted lines instead of raw tab-separated
input, so tail -n +N gives the agent readable content.
All 13 affected modules updated: container, dotnet, gh, glab, go, lint,
pnpm, pytest, rubocop, cargo, aws. 1884 tests pass.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
fix(tee): safe truncation caps and tee/hint coverage
Adds a TDD red test that asserts pre-existing user content in
.github/copilot-instructions.md must survive 'rtk init --copilot'.
Currently fails because run_copilot() uses write_if_changed() which
truncates the file.

Refs #1964
run_copilot() previously called write_if_changed() which truncated any
pre-existing .github/copilot-instructions.md, destroying user-authored
Copilot rules.

This routes copilot-instructions.md through upsert_rtk_block() (the
same idempotent marker-block helper already used for CLAUDE.md and
AGENTS.md). The COPILOT_INSTRUCTIONS constant is wrapped in
<!-- rtk-instructions v2 --> ... <!-- /rtk-instructions --> markers
so subsequent inits replace only RTK-owned content; the rest of the
file is preserved verbatim. Malformed pre-existing blocks (opening
marker without closing) are refused with a remediation message
rather than silently rewritten.

Fixes #1964, #1891
…formed paths

Adds five additional tests around copilot-instructions.md upsert:
- idempotent re-init (no duplicated blocks, identical content)
- stale RTK block in-place update with surrounding user content preserved
- dry-run never creates or modifies the file
- fresh install creates file with RTK marker block when no file exists
- malformed pre-existing block (opening marker without closing) is
  refused with a clear error rather than silently rewritten

Refs #1964
run_copilot(ctx) is now a thin wrapper around run_copilot_at(base, ctx);
tests pass a TempDir path so they no longer mutate process-global cwd.
This eliminates flakes when cargo test runs in parallel (the default).

The public API is unchanged; only the internal seam moves.

Refs #1964
The README badge and footer claimed MIT, but the LICENSE file is
Apache License 2.0. Updates both references so the README matches
the authoritative LICENSE file.

Closes #1996

Co-Authored-By: Claude <noreply@anthropic.com>
Following tee and hint refacto
Add global CAP constant to be inherited , to enable easier global configuration later
…he-2.0

docs(readme): fix license references to match LICENSE (Apache-2.0)
YOMXXX and others added 6 commits May 21, 2026 00:46
Address review feedback on #1976:

- Extract write_rtk_block() shared dispatcher: eliminates the duplicated
  4-arm RtkBlockUpsert match between run_claude_md_mode and the former
  upsert_copilot_instructions (now inlined). Both callers stay under the
  ~60-line guideline.
- Unify malformed handling: both paths now bail!() with a diagnostic and
  the exact recovery command. CLAUDE.md previously warned and exited 0,
  silently skipping the OpenCode plugin step; behaviour is now consistent.
- Reorder run_copilot_at: upsert copilot-instructions.md BEFORE writing
  the hook config so a malformed file aborts the install without leaving
  a stale .github/hooks/rtk-rewrite.json on disk.

Regression coverage:
- test_claude_md_mode_refuses_malformed_block mirrors the existing
  copilot malformed test against the shared dispatcher contract.
- test_copilot_init_malformed_leaves_no_hook_on_disk pins the new write
  order so a future re-order regression is caught.

cargo fmt / clippy --all-targets / test --bin rtk: clean (1909 passed).
fix(hooks/init): preserve user content in copilot-instructions.md
- Avoid underflow + 0 results caused by overwrite of global constant CAPS
- Soon user will be able to apply global configuration, this will change global CAPS and should not cause any underflow or 0 results, if overwrite sub >= CAPS -> use CAPS.
refacto(truncations): Set global CAPS for truncation
@aeppling
Copy link
Copy Markdown
Contributor Author

aeppling commented May 21, 2026

Found a blocker : git status regression in savings with -uall -procelain

Working on a fix , may revert #991 to merge this

aeppling and others added 2 commits May 22, 2026 10:13
The compact `git status` path ran `git status --porcelain -b -uall`. The
`-uall` flag expands fully-untracked directories into every file, while raw
`git status` collapses them (e.g. `node_modules/`). This made rtk output
larger than raw — measured ~29x on a 200-file untracked dir (5500B vs 191B) —
violating RTK's compress-or-match-raw invariant and inflating tokens.

Remove `-uall` so untracked directories collapse exactly like raw. This keeps
#991's actual fix intact: all modified/staged/renamed/conflict paths are still
shown with no grouped summaries or `... +N more` overflow markers (`-uall`
never affected those lines). Untracked files in partially-tracked dirs and any
paths git itself expands are still preserved by the formatter.

Measured (rtk vs raw git status):
- node_modules/ (200 files): 5500B (-2780%) -> 25B (+87% savings)
- normal (8 mod + 2 untracked): +71% -> +76%
- 17 modified (#991 case): unchanged at +58%, all 17 shown, 0 overflow markers

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
fix(git): drop -uall from compact status so output never exceeds raw
Copy link
Copy Markdown
Collaborator

@pszymkowiak pszymkowiak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Approved — revue approfondie

Revue ligne à ligne au HEAD 06476d17 (et non via gh pr diff, qui sert un diff caché périmé), complétée par des tests empiriques de git status sur plusieurs gros repos OSS.

Qualité élevée et homogène. Points forts :

  • core/truncate.rs : caps centralisés + reduced() const fn underflow-safe, appliqué uniformément sur ~30 modules.
  • Récupération sur troncature (force_tee_tail_hint) avec offsets corrects (MAX+1, MAX+2 pour docker-images), convention documentée.
  • git push en streaming (#1531) : règle le timeout 30s, préserve les remote:, ne résume pas sur échec.
  • init.rs (#1976) : write_rtk_block upsert par marqueurs + atomic_write + refus des blocs malformés → préserve réellement le contenu utilisateur.
  • Hygiène RTK respectée : aucun unwrap/async/Regex::new/panic hors tests.

Le point que je jugeais bloquant a été corrigé : le commit « drop -uall from compact status so output never exceeds raw » fait que git status ne dépasse plus jamais la sortie brute (un dossier untracked redevient une seule ligne).

Points mineurs, non bloquants (à traiter idéalement avant le tag)

  1. Doc désynchronisée : src/cmds/git/README.md:8 indique encore --porcelain -b -uall (et « nested untracked files stay visible »), alors que -uall a été retiré du code. À corriger.
  2. format_status_inner reste sans cap ni test de savings : sur un gros codemod (beaucoup de fichiers tracked modifiés), la compression est modeste (~30–50 %). Acceptable comme choix produit (#991), mais un test de non-régression « never exceeds raw » serait précieux.

LGTM 🚢

docs(git): sync status README with --porcelain -b
@aeppling aeppling merged commit 9c943d6 into master May 22, 2026
21 checks passed
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.

8 participants