Skip to content

filter package.json passthrough tasks from shell completions#9

Closed
kjanat wants to merge 2 commits intomasterfrom
claude/deduplicate-monorepo-tasks-co3WG
Closed

filter package.json passthrough tasks from shell completions#9
kjanat wants to merge 2 commits intomasterfrom
claude/deduplicate-monorepo-tasks-co3WG

Conversation

@kjanat
Copy link
Copy Markdown
Owner

@kjanat kjanat commented May 5, 2026

Summary

This change improves shell completion behavior by filtering out package.json tasks that are passthrough wrappers to turbo.json tasks. This follows the canonical Turborepo pattern where package.json scripts like "build": "turbo run build" delegate to turbo, and such passthroughs should not clutter completion suggestions.

Key Changes

  • Passthrough detection: Added logic to identify when a package.json task shares its name with a turbo.json task, treating it as a passthrough wrapper
  • Completion filtering: package.json passthrough tasks are now excluded from completion candidates entirely, while still being surfaced by runner list for transparency
  • Duplicate handling: Updated the duplicate detection logic to count only "effective" (non-passthrough) tasks, ensuring correct qualification of remaining candidates
  • Test coverage: Added two comprehensive test cases:
    • package_json_passthrough_to_turbo_collapses_to_bare_name: Verifies that a passthrough task results in only the bare name appearing once
    • passthrough_swallow_keeps_unrelated_runner_qualified_forms: Ensures that when other task sources (e.g., Makefile) also define the same task name, they retain their qualified forms for disambiguation

Implementation Details

  • Uses a HashMap<&str, HashSet<TaskSource>> to track all sources for each task name
  • The is_turbo_passthrough closure checks if a task is from package.json AND has a corresponding turbo.json source
  • Passthrough tasks are skipped during both the effective count calculation and candidate generation loops
  • The change maintains backward compatibility with runner list and runner build commands, which continue to surface all sources per their existing priority ordering

https://claude.ai/code/session_01S5a1HBiSU1YBeRbebcbLWf

In a Turborepo monorepo, the canonical wiring is a root package.json
with `"build": "turbo run build"` mirroring a same-named entry in
turbo.json. Tab completion was emitting both the package.json and
turbo.json qualified forms (`package.json:build`, `turbo.json:build`)
plus the bare name — three candidates for what is functionally one
task.

When a task name appears in both sources, drop the package.json entry
from completion candidates entirely. This is consistent with the
existing run-priority order (TurboJson > PackageJson), so `runner build`
was already dispatching through turbo. `runner list` keeps showing both
sources for transparency, and a typed `package.json:build` still works.

If a third source (e.g. Makefile) also defines the name, both turbo and
the third source keep their qualified forms — only the package.json
wrapper is suppressed.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 5, 2026

Review Change Stack

📝 Walkthrough

fix: filter passthrough package.json tasks from shell completions

When a task exists in both package.json and turbo.json, the package.json entry
(typically a passthrough like "build": "turbo run build") is now excluded from
shell completion candidates. This eliminates redundant completion suggestions for
the same effective task while preserving backward compatibility.

Changes:

  • Detection of turbo passthrough tasks: identifies package.json tasks that share
    a name with turbo.json tasks and treats them as passthrough wrappers
  • Completion filtering: passthrough package.json tasks are skipped when
    generating shell completion candidates
  • Duplicate handling: duplicate-detection now counts only effective (non-passthrough)
    tasks to correctly qualify remaining candidates
  • The runner list command continues to surface both sources for transparency
  • Explicit qualified invocation (e.g., package.json:build) still works

Implementation uses a HashMap to track sources per task name, with an
is_turbo_passthrough closure identifying passthroughs that are skipped during
effective-count and candidate-generation loops.

Tests:

  • Verify passthrough collapsing to a single bare task name
  • Ensure other sources (e.g., Makefile) retain qualified forms when collisions exist

Bumps version to 0.6.0 and updates CHANGELOG.md.

Walkthrough

task_candidates_from now treats a package.json task as a "turbo passthrough" when the same name exists in turbo.json, excluding the package.json candidate from shell completions; duplicate counting and bare/qualified emission are adjusted and two tests plus changelog and version bump added.

Changes

Turbo Passthrough Completion Handling

Layer / File(s) Summary
Passthrough Detection & Data Shape
src/cli.rs (lines 52–78)
Introduces sources_for_name mapping and is_turbo_passthrough logic to identify and exclude package.json entries when turbo.json defines the same task name.
Candidate Emission & Duplicate Counting
src/cli.rs (lines 114–117, 79–85, 108–117)
Computes effective_count that ignores swallowed passthrough tasks and ensures bare candidate emission is gated by seen_bare after passthrough exclusion; qualified candidates are emitted based on effective duplicates.
Test Coverage
src/cli.rs (lines 185–270)
Adds tests: package_json_passthrough_to_turbo_collapses_to_bare_name and passthrough_swallow_keeps_unrelated_runner_qualified_forms validating passthrough collapsing and preservation of unrelated qualified forms.
Changelog Update
CHANGELOG.md (lines 10–20)
Adds Unreleased → Fixed entry documenting the completion fix that drops redundant package.json:<task> candidates when turbo.json defines the same task.
Version Bump
Cargo.toml (line 3)
Bumps crate version from 0.5.0 to 0.6.0.

Poem

Arrr, the duplicates walked the plank! ⚓
Turbo claimed the prize, package hid its flag,
Bare names stand tidy on the deck, no more drag,
Tests keep watch while changelogs mark the snag,
Version hoisted — 0.6.0 — brisk as a gag! 🏴‍☠️

🚥 Pre-merge checks | ✅ 6 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Changelog Update ⚠️ Warning Cargo.toml bumped to 0.6.0 but CHANGELOG.md lacks required ## [0.6.0] - YYYY-MM-DD section. Entry only under ## [Unreleased]. Create new ## [0.6.0] - 2026-05-08 section and move the Fixed entry there from Unreleased to match the version bump requirement.
Semver Version Bump Validation ⚠️ Warning Version bumped 0.5.0→0.6.0 (MINOR) but contains BREAKING changes: 4 public fns removed from src/lib.rs & TaskSource::CargoAliases enum variant removed. Should be 1.0.0 (MAJOR bump). Bump version to 0.6.0 is INCORRECT for breaking changes. Must increment MAJOR to 1.0.0. Also: CHANGELOG.md entry currently under [Unreleased] must move to [0.6.0] - 2026-05-08 section.
✅ Passed checks (6 passed)
Check name Status Explanation
Title check ✅ Passed Aye, the title be descriptive and captures the essence of the change, but it be 60 characters—just 10 over the preferred 50-character mark. Follows conventional commit guidelines with a lowercase action verb ('filter') and clearly describes the fix.
Description check ✅ Passed Shiver me timbers! The description be spot-on—it explains the passthrough detection, completion filtering, duplicate handling, and test coverage in fine detail. Every word relates directly to the changeset, and it be comprehensive as a proper ship's manifest.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Agents.Md Documentation Updated ✅ Passed No AGENTS.md file found in repository. Custom check is not applicable since the condition requiring AGENTS.md existence is not met.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
⚔️ Resolve merge conflicts
  • Resolve merge conflict in branch claude/deduplicate-monorepo-tasks-co3WG
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch claude/deduplicate-monorepo-tasks-co3WG

Comment @coderabbitai help to get the list of available commands and usage tips.

@kjanat kjanat self-assigned this May 8, 2026
@kjanat kjanat changed the title Filter package.json passthrough tasks from shell completions filter package.json passthrough tasks from shell completions May 8, 2026
Address CodeRabbit pre-merge warnings: log the completion-dedup fix
under Unreleased and bring the crate version up to 0.6.0 to clear the
SemVer regression flag versus master.
@cloudflare-workers-and-pages
Copy link
Copy Markdown

cloudflare-workers-and-pages Bot commented May 8, 2026

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Updated (UTC)
❌ Deployment failed
View logs
runner f4dad27 May 08 2026, 11:17 PM

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@CHANGELOG.md`:
- Around line 8-20: The CHANGELOG entry currently under "## [Unreleased]" must
be moved into a new release section matching the bumped version; create a header
"## [0.6.0] - 2026-05-08" and place the "Fixed" bullet (the paragraph about
dropping redundant `package.json:<task>` entries) under that section instead of
Unreleased, leaving Unreleased empty or with only truly unreleased changes;
ensure the header text exactly matches `0.6.0` and the date format `YYYY-MM-DD`.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: c332d4bc-c18e-4316-ae3f-a168d42abcda

📥 Commits

Reviewing files that changed from the base of the PR and between 41bafbe and f4dad27.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (2)
  • CHANGELOG.md
  • Cargo.toml
📜 Review details
⏰ Context from checks skipped due to timeout of 18000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Workers Builds: runner
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: Analyze (rust)
  • GitHub Check: Analyze (actions)
🧰 Additional context used
📓 Path-based instructions (2)
@(package.json|pyproject.toml|setup.py|Cargo.toml|go.mod|pom.xml|build.gradle|VERSION)

📄 CodeRabbit inference engine (Custom checks)

@(package.json|pyproject.toml|setup.py|Cargo.toml|go.mod|pom.xml|build.gradle|VERSION): If any source code files (excluding tests, docs, CI, markdown, or comments-only changes) are modified, then a version field MUST be updated in one of the following files if present in the repo: package.json, pyproject.toml, setup.py, Cargo.toml, go.mod, pom.xml, build.gradle, or a VERSION file.
The new version MUST follow SemVer (MAJOR.MINOR.PATCH). If the PR introduces breaking changes (removal or renaming of public APIs, changes to function signatures, deleted exported symbols, or incompatible config changes), MAJOR must increment. If it adds backward-compatible functionality, MINOR must increment. If it only fixes bugs without changing public APIs, PATCH must increment.

Files:

  • Cargo.toml
**/CHANGELOG.md

📄 CodeRabbit inference engine (Custom checks)

**/CHANGELOG.md: If any source code files (excluding tests, docs, CI, markdown, or comments-only changes) are modified, CHANGELOG.md MUST also be modified in the same PR.
If a version bump is detected, CHANGELOG.md MUST contain a new section header matching the exact new version number in the format: '## [X.Y.Z] - YYYY-MM-DD'.
If NO version bump is detected, the changes in the PR MUST be added under the existing '## [Unreleased]' section in CHANGELOG.md. The entry MUST describe the changes (e.g., Added, Changed, Fixed, Removed).

Files:

  • CHANGELOG.md
🧠 Learnings (1)
📚 Learning: 2026-03-26T16:14:15.754Z
Learnt from: kjanat
Repo: kjanat/runner PR: 1
File: src/tool/go_task.rs:64-81
Timestamp: 2026-03-26T16:14:15.754Z
Learning: If code uses let-chains (e.g., `if let Some(x) = foo && ... && let Some(y) = bar`), ensure the crate’s `Cargo.toml` sets `package.edition = "2024"`. Rust 2021/earlier should not be used with let-chains; require 2024 specifically for compilation.

Applied to files:

  • Cargo.toml
🔇 Additional comments (1)
Cargo.toml (1)

3-3: Aye, this version bump is correct and properly SemVer-formatted.

Line 3 is aligned with the release intent (0.6.0) and the file stays internally consistent.

Comment thread CHANGELOG.md
Comment on lines 8 to +20
## [Unreleased]

### Fixed

- Drop redundant `package.json:<task>` qualified entries from shell
completion when the same name exists in `turbo.json`. In a Turborepo
monorepo the root `package.json` script is canonically a passthrough
(`"build": "turbo run build"`), so emitting both `package.json:build`
and `turbo.json:build` alongside the bare `build` produced three
candidates for one effective task. The package.json entry is now
swallowed in completion output; `runner list` still surfaces both
sources, and a typed `package.json:<task>` still resolves manually.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Move this entry into a 0.6.0 section, matey — Unreleased is wrong after the version bump.

Since Cargo.toml is already 0.6.0, this change must be recorded under a new header like ## [0.6.0] - 2026-05-08, not only under ## [Unreleased].

As per coding guidelines: “If a version bump is detected, CHANGELOG.md MUST contain a new section header matching the exact new version number in the format: ## [X.Y.Z] - YYYY-MM-DD.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@CHANGELOG.md` around lines 8 - 20, The CHANGELOG entry currently under "##
[Unreleased]" must be moved into a new release section matching the bumped
version; create a header "## [0.6.0] - 2026-05-08" and place the "Fixed" bullet
(the paragraph about dropping redundant `package.json:<task>` entries) under
that section instead of Unreleased, leaving Unreleased empty or with only truly
unreleased changes; ensure the header text exactly matches `0.6.0` and the date
format `YYYY-MM-DD`.

@kjanat
Copy link
Copy Markdown
Owner Author

kjanat commented May 8, 2026

re-opening new pr

@kjanat kjanat closed this May 8, 2026
@kjanat kjanat deleted the claude/deduplicate-monorepo-tasks-co3WG branch May 8, 2026 23:24
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