Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
5b57c42
fix: P1 exit codes, grep regex perf, SQLite WAL (#631)
pszymkowiak Mar 16, 2026
0414020
fix: raise output caps for P0 bugs (#617, #618, #620) (#630)
pszymkowiak Mar 16, 2026
b29344f
feat(.claude): add /rtk-triage skill — cross-analysis of PRs and issu…
FlorianBruniaux Mar 17, 2026
ff8e490
fix: subcommand routing drops unrecognized subcommands (#600) (#601)
pszymkowiak Mar 17, 2026
810d7ff
fix: resolve cargo fmt + 54 clippy warnings blocking CI (#663)
pszymkowiak Mar 17, 2026
8b162fe
fix: discover absolute paths + git global options (#485, #163) (#518)
pszymkowiak Mar 17, 2026
1be3589
fix: prevent double `--` separator in cargo clippy with -p flags (#519)
ousamabenyounes Mar 17, 2026
945ee34
ci: add PR template + target branch check (#521)
pszymkowiak Mar 17, 2026
cf1a790
fix: prevent rtk read from corrupting JSON/YAML/data files (#522)
ousamabenyounes Mar 17, 2026
9b4b5a8
fix: skip rewriting find/fd in pipes to preserve xargs compatibility …
pszymkowiak Mar 17, 2026
f2a7306
fix: add hint when git diff is truncated + fix --no-compact passthrou…
pszymkowiak Mar 17, 2026
91b96bf
fix: propagate exit codes in git diff, status+args, commit, and branc…
pszymkowiak Mar 17, 2026
fab035e
feat: add 5 new TOML filters (ollama, nx, gradle, spring-boot, jira) …
pszymkowiak Mar 17, 2026
c2cc8f3
fix: replace emojis with plain text in git status output (#603) (#638)
pszymkowiak Mar 17, 2026
31aef18
feat(flutter): add Flutter command filters for test, analyze, build, pub
copperspeed Mar 17, 2026
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
237 changes: 237 additions & 0 deletions .claude/skills/rtk-triage/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,237 @@
---
description: >
Triage complet RTK : exécute issue-triage + pr-triage en parallèle,
puis croise les données pour détecter doubles couvertures, trous sécurité,
P0 sans PR, et conflits internes. Sauvegarde dans claudedocs/RTK-YYYY-MM-DD.md.
Args: "en"/"fr" pour la langue (défaut: fr), "save" pour forcer la sauvegarde.
allowed-tools:
- Bash
- Write
- Read
- AskUserQuestion
---

# /rtk-triage

Orchestrateur de triage RTK. Fusionne issue-triage + pr-triage et produit une analyse croisée.

---

## Quand utiliser

- Hebdomadaire ou avant chaque sprint
- Quand le backlog PR/issues grossit rapidement
- Pour identifier les doublons avant de reviewer

---

## Workflow en 4 phases

### Phase 0 — Préconditions

```bash
git rev-parse --is-inside-work-tree
gh auth status
```

Vérifier que la date actuelle est connue (utiliser `date +%Y-%m-%d`).

---

### Phase 1 — Data gathering (parallèle)

Lancer les deux collectes simultanément :

**Issues** :
```bash
gh repo view --json nameWithOwner -q .nameWithOwner

gh issue list --state open --limit 150 \
--json number,title,author,createdAt,updatedAt,labels,assignees,body

gh issue list --state closed --limit 20 \
--json number,title,labels,closedAt

gh api "repos/{owner}/{repo}/collaborators" --jq '.[].login'
```

**PRs** :
```bash
gh pr list --state open --limit 60 \
--json number,title,author,createdAt,updatedAt,additions,deletions,changedFiles,isDraft,mergeable,reviewDecision,statusCheckRollup,body

# Pour chaque PR, récupérer les fichiers modifiés (nécessaire pour overlap detection)
# Prioriser les PRs candidates (même domaine, même auteur)
gh pr view {num} --json files --jq '[.files[].path] | join(",")'
```

---

### Phase 2 — Triage individuel

Exécuter les analyses de `/issue-triage` et `/pr-triage` séparément (même logique que les skills individuels) pour produire :

**Issues** :
- Catégorisation (Bug/Feature/Enhancement/Question/Duplicate)
- Risque (Rouge/Jaune/Vert)
- Staleness (>30j)
- Map `issue_number → [PR numbers]` via scan `fixes #N`, `closes #N`, `resolves #N`

**PRs** :
- Taille (XS/S/M/L/XL)
- CI status (clean/dirty)
- Nos PRs vs externes
- Overlaps (>50% fichiers communs entre 2 PRs)
- Clusters (auteur avec 3+ PRs)

Afficher les tableaux standards de chaque skill (voir SKILL.md de issue-triage et pr-triage pour le format exact).

---

### Phase 3 — Analyse croisée (cœur de ce skill)

C'est ici que ce skill apporte de la valeur au-delà des deux skills individuels.

#### 3.1 Double couverture — 2 PRs pour 1 issue

Pour chaque issue liée à ≥2 PRs (via scan des bodies + overlap fichiers) :

| Issue | PR1 (infos) | PR2 (infos) | Verdict recommandé |
|-------|-------------|-------------|-------------------|
| #N (titre) | PR#X — auteur, taille, CI | PR#Y — auteur, taille, CI | Garder la plus ciblée. Fermer/coordonner l'autre |

Règle de verdict :
- Préférer la plus petite (XS < S < M) si même scope
- Préférer CI clean sur CI dirty
- Préférer "nos PRs" si l'une est interne
- Si overlap de fichiers >80% → conflit quasi-certain, signaler

#### 3.2 Trous de couverture sécurité

Pour chaque issue rouge (#640-type security review) :
- Lister les sous-findings mentionnés dans le body
- Croiser avec les PRs existantes (mots-clés dans titre/body)
- Identifier les findings sans PR

Format :
```
## Issue #N — security review (finding par finding)
| Finding | PR associée | Status |
|---------|-------------|--------|
| Description finding 1 | PR#X | En review |
| **Description finding critique** | **AUCUNE** | ⚠️ Trou |
```

#### 3.3 P0/P1 bugs sans PR

Issues labelisées P0 ou P1 (ou mots-clés : "crash", "truncat", "cap", "hardcoded") sans aucune PR liée.

Format :
```
## Bugs critiques sans PR
| Issue | Titre | Pattern commun | Effort estimé |
|-------|-------|----------------|---------------|
```

Chercher un pattern commun (ex: "cap hardcodé", "exit code perdu") — si 3+ bugs partagent un pattern, suggérer un sprint groupé.

#### 3.4 Nos PRs dirty — causes probables

Pour chaque PR interne avec CI dirty ou CONFLICTING :
- Vérifier si un autre PR touche les mêmes fichiers
- Vérifier si un merge récent sur develop peut expliquer le conflit
- Recommander : rebase, fermeture, ou attente

Format :
```
## Nos PRs dirty
| PR | Issue(s) | Cause probable | Action |
|----|----------|----------------|--------|
```

#### 3.5 PRs sans issue trackée

PRs internes sans `fixes #N` dans le body — signaler pour traçabilité.

---

### Phase 4 — Output final

#### Afficher l'analyse croisée complète (sections 3.1 → 3.5)

Puis afficher le résumé chiffré :

```
## Résumé chiffré — YYYY-MM-DD

| Catégorie | Count |
|-----------|-------|
| PRs prêtes à merger (nos) | N |
| Quick wins externes | N |
| Double couverture (conflicts) | N paires |
| P0/P1 bugs sans PR | N |
| Security findings sans PR | N |
| Nos PRs dirty à rebaser | N |
| PRs à fermer (recommandé) | N |
```

#### Sauvegarder dans claudedocs

```bash
date +%Y-%m-%d # Pour construire le nom de fichier
```

Sauvegarder dans `claudedocs/RTK-YYYY-MM-DD.md` avec :
- Les tableaux de triage issues + PRs (Phase 2)
- L'analyse croisée complète (Phase 3)
- Le résumé chiffré

Confirmer : `Sauvegardé dans claudedocs/RTK-YYYY-MM-DD.md`

---

## Format du fichier sauvegardé

```markdown
# RTK Triage — YYYY-MM-DD

Croisement issues × PRs. {N} PRs ouvertes, {N} issues ouvertes.

---

## 1. Double couverture
...

## 2. Trous sécurité
...

## 3. P0/P1 sans PR
...

## 4. Nos PRs dirty
...

## 5. Nos PRs prêtes à merger
...

## 6. Quick wins externes
...

## 7. Actions prioritaires
(liste ordonnée par impact/urgence)

---

## Résumé chiffré
...
```

---

## Règles

- Langue : argument `en`/`fr`. Défaut : `fr`. Les commentaires GitHub restent toujours en anglais.
- Ne jamais poster de commentaires GitHub sans validation utilisateur (AskUserQuestion).
- Si >150 issues ou >60 PRs : prévenir l'utilisateur, proposer de filtrer par label ou date.
- L'analyse croisée (Phase 3) est toujours exécutée — c'est la valeur ajoutée de ce skill.
- Le fichier claudedocs est sauvegardé automatiquement sauf si l'utilisateur dit "no save".
13 changes: 13 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
## Summary
<!-- What does this PR do? Keep it short (1-3 bullet points). -->

-

## Test plan
<!-- How did you verify this works? -->

- [ ] `cargo fmt --all && cargo clippy --all-targets && cargo test`
- [ ] Manual testing: `rtk <command>` output inspected

> **Important:** All PRs must target the `develop` branch (not `master`).
> See [CONTRIBUTING.md](../blob/master/CONTRIBUTING.md) for details.
43 changes: 43 additions & 0 deletions .github/workflows/pr-target-check.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
name: PR Target Branch Check

on:
pull_request_target:
types: [opened, edited]

jobs:
check-target:
runs-on: ubuntu-latest
# Skip develop→master PRs (maintainer releases)
if: >-
github.event.pull_request.base.ref == 'master' &&
github.event.pull_request.head.ref != 'develop'
steps:
- name: Add wrong-base label
uses: actions/github-script@v7
with:
script: |
const pr = context.payload.pull_request;

// Add label
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: pr.number,
labels: ['wrong-base']
});

// Post comment
const body = `👋 Thanks for the PR! It looks like this targets \`master\`, but all PRs should target the **\`develop\`** branch.

Please update the base branch:
1. Click **Edit** at the top right of this PR
2. Change the base branch from \`master\` to \`develop\`

See [CONTRIBUTING.md](https://github.com/${context.repo.owner}/${context.repo.repo}/blob/master/CONTRIBUTING.md) for details.`;

await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: pr.number,
body: body
});
2 changes: 1 addition & 1 deletion ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ SHARED utils.rs Helpers N/A ✓
tee.rs Full output recovery N/A ✓
```

**Total: 60 modules** (38 command modules + 22 infrastructure modules)
**Total: 66 modules** (44 command modules + 22 infrastructure modules)

### Module Count Breakdown

Expand Down
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@ All notable changes to rtk (Rust Token Killer) will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]


### Features

* **flutter:** add Flutter command filters for `flutter test`, `flutter analyze`, `flutter build`, and `flutter pub get/upgrade`

## [0.29.0](https://github.com/rtk-ai/rtk/compare/v0.28.2...v0.29.0) (2026-03-12)


Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ rtk playwright test # E2E results (failures only)
rtk pytest # Python tests (-90%)
rtk go test # Go tests (NDJSON, -90%)
rtk cargo test # Cargo tests (-90%)
rtk flutter test # Flutter tests (-90%)
```

### Build & Lint
Expand All @@ -184,6 +185,8 @@ rtk cargo build # Cargo build (-80%)
rtk cargo clippy # Cargo clippy (-80%)
rtk ruff check # Python linting (JSON, -80%)
rtk golangci-lint run # Go linting (JSON, -85%)
rtk flutter analyze # Flutter analyze (warnings+errors, -80%)
rtk flutter build apk # Flutter build (result only, -85%)
```

### Package Managers
Expand Down Expand Up @@ -329,6 +332,7 @@ cp hooks/opencode-rtk.ts ~/.config/opencode/plugins/rtk.ts
| `pytest` | `rtk pytest` |
| `pip list/install` | `rtk pip ...` |
| `go test/build/vet` | `rtk go ...` |
| `flutter test/analyze/build/pub` | `rtk flutter ...` |
| `golangci-lint` | `rtk golangci-lint` |
| `docker ps/images/logs` | `rtk docker ...` |
| `kubectl get/logs` | `rtk kubectl ...` |
Expand Down
41 changes: 41 additions & 0 deletions src/cargo_cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ fn restore_double_dash_with_raw(args: &[String], raw_args: &[String]) -> Vec<Str
return args.to_vec();
}

// If args already contain `--` (Clap preserved it), no restoration needed
if args.iter().any(|a| a == "--") {
return args.to_vec();
}

// Find `--` in the original command line
let sep_pos = match raw_args.iter().position(|a| a == "--") {
Some(pos) => pos,
Expand Down Expand Up @@ -1054,6 +1059,42 @@ mod tests {
assert_eq!(result, vec!["--", "-D", "warnings"]);
}

#[test]
fn test_restore_double_dash_clippy_with_package_flags() {
// rtk cargo clippy -p my-service -p my-crate -- -D warnings
// Clap with trailing_var_arg preserves "--" when args precede it
// → clap gives ["-p", "my-service", "-p", "my-crate", "--", "-D", "warnings"]
let args: Vec<String> = vec![
"-p".into(),
"my-service".into(),
"-p".into(),
"my-crate".into(),
"--".into(),
"-D".into(),
"warnings".into(),
];
let raw = vec![
"rtk".into(),
"cargo".into(),
"clippy".into(),
"-p".into(),
"my-service".into(),
"-p".into(),
"my-crate".into(),
"--".into(),
"-D".into(),
"warnings".into(),
];
let result = restore_double_dash_with_raw(&args, &raw);
// Should NOT double the "--"
assert_eq!(
result,
vec!["-p", "my-service", "-p", "my-crate", "--", "-D", "warnings"]
);
// Verify only one "--" exists
assert_eq!(result.iter().filter(|a| *a == "--").count(), 1);
}

#[test]
fn test_filter_cargo_build_success() {
let output = r#" Compiling libc v0.2.153
Expand Down
Loading