Skip to content

fix: thread recursive option from plugin protocol to worktree create - #25

Merged
mateodelnorte merged 3 commits into
mainfrom
fix-recursive-option
Mar 29, 2026
Merged

mateodelnorte merged 3 commits into
mainfrom
fix-recursive-option

Conversation

@mateodelnorte

@mateodelnorte mateodelnorte commented Mar 29, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • The host meta CLI strips --recursive from command args and passes it as a plugin protocol option (options.recursive)
  • execute_worktree_command never threaded this option through to clap arg parsing, so CreateArgs.recursive was always false
  • This meant build_nested_dep_graph was never invoked, and transitive depends_on entries in nested .meta.yaml files were silently ignored

Fix

  • Add recursive: bool parameter to execute_worktree_command
  • Pass options.recursive from the plugin dispatch in lib.rs
  • Inject --recursive back into clap args when the protocol option is set

Test plan

  • meta git worktree create test --repo open-source/gitkb/core --recursive now includes vendor/tree-sitter-markdown
  • cargo check succeeds in the resulting worktree
  • Non-recursive worktree creation still works as before

🤖 Generated with Claude Code

Implements [[tasks/harmony-407]]

Summary by CodeRabbit

  • New Features

    • Worktree commands gain a recursive mode that can be automatically applied when appropriate, enabling operations to span nested worktrees without manual flag changes.
  • Chores

    • Added an automated notification workflow that alerts a parent repository on main-branch pushes via a repository-dispatch event.

mateodelnorte and others added 2 commits March 26, 2026 08:21
Re-adds notify-parent.yml to trigger parent meta repo's release-please
when this child repo merges to main. Simplified: no checkout needed,
all payload fields properly quoted with toJSON.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The host meta CLI strips --recursive from command args and passes it as a
plugin protocol option. The worktree create handler was reading recursive
from clap-parsed args (always false) instead of the protocol option.

Inject --recursive back into clap args when the protocol option is set,
so build_nested_dep_graph is invoked and transitive depends_on entries
(e.g. core -> vendor/tree-sitter-markdown) are resolved correctly.

Implements [[tasks/harmony-407]]

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Mar 29, 2026 •

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 09f296dc-84c2-4bc1-b1af-e5267bab9f5b

📥 Commits

Reviewing files that changed from the base of the PR and between ce1c86e and 894960d.

📒 Files selected for processing (1)
  • src/commands/worktree/mod.rs

Walkthrough

Adds a GitHub Actions workflow that notifies a parent repo on pushes to main, and extends the worktree command to accept a recursive: bool that can inject --recursive into the executed arguments when appropriate.

Changes

Cohort / File(s) Summary
GitHub Actions Workflow
​.github/workflows/notify-parent.yml
New workflow triggered on push to main that calls peter-evans/repository-dispatch against the parent repo with event-type: child-repo-updated and a JSON client-payload (repo name, commit SHA, actor). Workflow-level permissions set to {}.
Worktree Command
src/commands/worktree/mod.rs
Function signature of execute_worktree_command updated to add recursive: bool; clap_args made mutable and --recursive is conditionally injected for the create subcommand when recursive is true and no --recursive/-r present.
Call Site Update
src/lib.rs
Passes options.recursive into commands::worktree::execute_worktree_command(...) to propagate the new parameter.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Dev as Dev (push)
  participant GH as GitHub Actions
  participant Action as repository-dispatch Action
  participant Parent as Parent Repo (meta)

  Dev->>GH: push to main
  GH->>Action: run repository-dispatch with event `child-repo-updated` and payload (repo, sha, actor)
  Action->>Parent: repository dispatch event
  Parent-->>GH: (optional) handle event / trigger workflows
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐰 I hopped a commit down the burrowed lane,
Sent a little ping to kin across the plain,
A flag tucked gently in a worktree's sleeve,
Now parent and child share the stories we weave,
Carrots and commits — a tiny, merry refrain.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: threading the recursive option from the plugin protocol through to worktree create functionality, which is the primary purpose of this PR.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix-recursive-option

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

@greptile-apps

greptile-apps Bot commented Mar 29, 2026 •

Copy link
Copy Markdown

Greptile Summary

This PR fixes a silent bug where the --recursive flag from the meta host CLI was never forwarded into the worktree create command, causing transitive depends_on dependencies in nested .meta.yaml files to be silently ignored. It also adds a new GitHub Actions workflow to notify the parent harmony-labs/meta repository whenever a push lands on main.

Key changes:

  • execute_worktree_command gains a recursive: bool parameter and injects --recursive back into clap args when the protocol option is set
  • lib.rs threads options.recursive through to execute_worktree_command
  • New notify-parent.yml workflow dispatches a child-repo-updated event to the parent repo on every push to main

Issues found:

  • The --recursive injection is not gated to the create subcommand. Every other worktree subcommand (list, status, remove, add, prune, diff, exec) does not declare this flag, so any invocation of those commands when options.recursive is true (e.g. meta --recursive git worktree list) will now fail with a clap parse error instead of succeeding as before — a regression.
  • The injection runs before the clap_args.is_empty() guard, so meta --recursive git worktree (no subcommand) produces a confusing error instead of the clean help text.

Confidence Score: 4/5

Safe to merge after scoping the --recursive injection to the create subcommand to avoid regressions on other worktree commands.

There is one clear P1 regression: any worktree subcommand other than create will fail with a clap parse error whenever the global --recursive flag is present. The fix is targeted and not risky; the overall approach of threading the protocol option back into clap args is sound.

src/commands/worktree/mod.rs — the injection logic needs to be scoped to create and the ordering relative to the empty-args guard should be corrected.

Important Files Changed

Filename Overview
src/commands/worktree/mod.rs Adds recursive parameter and injects --recursive into clap args, but the injection is not scoped to the create subcommand and bypasses the empty-args help guard.
src/lib.rs Threads options.recursive through to execute_worktree_command; straightforward, correct change.
.github/workflows/notify-parent.yml New workflow to dispatch a child-repo-updated event to the parent harmony-labs/meta repo on push to main; uses a pinned action SHA and a PAT secret, with correctly scoped permissions: {}.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["meta CLI receives\n--recursive flag"] --> B["Strip --recursive,\nset options.recursive = true"]
    B --> C["execute_command()\nin lib.rs"]
    C --> D{"starts_with\n'worktree' or\n'git worktree'?"}
    D -- Yes --> E["execute_worktree_command(\n  ..., recursive=true\n)"]
    E --> F["Build clap_args\nfrom command + args"]
    F --> G{"recursive &&\n--recursive not\nalready in args?"}
    G -- Yes --> H["clap_args.push('--recursive')"]
    G -- No --> I["clap_args unchanged"]
    H --> J{"clap_args is_empty?"}
    I --> J
    J -- Yes --> K["show help"]
    J -- No --> L["WorktreeParser::try_parse_from(clap_args)"]
    L --> M{"subcommand?"}
    M -- create --> N["handle_create(args)\nwith recursive=true ✓"]
    M -- "list/status/remove/etc." --> O["❌ clap error: unexpected --recursive\n(P1 regression)"]
    D -- No --> P["dispatch to other git command handlers"]
Loading

Comments Outside Diff (1)

  1. src/commands/worktree/mod.rs, line 59-69 (link)

    P2 Injection before empty-args guard bypasses help display

    The --recursive injection executes before the clap_args.is_empty() guard. If a user runs meta --recursive git worktree (no subcommand) the injection turns the empty vec into ["--recursive"], the is_empty() branch is never reached, and clap returns a cryptic "required argument missing" error instead of the intended help text.

    Moving the empty check before the injection would preserve the clean help path:

    // No subcommand at all — show help (check before flag injection)
    if clap_args.is_empty() {
        print_worktree_help();
        return CommandResult::Message(String::new());
    }
    
    if recursive && !clap_args.iter().any(|a| a == "--recursive" || a == "-r") {
        clap_args.push("--recursive".to_string());
    }
    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: src/commands/worktree/mod.rs
    Line: 59-69
    
    Comment:
    **Injection before empty-args guard bypasses help display**
    
    The `--recursive` injection executes before the `clap_args.is_empty()` guard. If a user runs `meta --recursive git worktree` (no subcommand) the injection turns the empty vec into `["--recursive"]`, the `is_empty()` branch is never reached, and clap returns a cryptic "required argument missing" error instead of the intended help text.
    
    Moving the empty check before the injection would preserve the clean help path:
    
    ```rust
    // No subcommand at all — show help (check before flag injection)
    if clap_args.is_empty() {
        print_worktree_help();
        return CommandResult::Message(String::new());
    }
    
    if recursive && !clap_args.iter().any(|a| a == "--recursive" || a == "-r") {
        clap_args.push("--recursive".to_string());
    }
    ```
    
    How can I resolve this? If you propose a fix, please make it concise.
Prompt To Fix All With AI
This is a comment left during a code review.
Path: src/commands/worktree/mod.rs
Line: 59-63

Comment:
**`--recursive` injected for all subcommands, not just `create`**

`--recursive` / `-r` is only declared in `CreateArgs`. Every other worktree subcommand (`list`, `status`, `remove`, `add`, `prune`, `diff`, `exec`) does not expose this flag. When `options.recursive` is `true` (i.e. the user ran any meta command with the global `--recursive` flag), the injection will cause clap to fail with an "unexpected argument" error for every worktree subcommand that isn't `create`.

For example, `meta --recursive git worktree list` would produce a clap parse error after this change, whereas it previously worked correctly.

The injection should be guarded to only apply when the dispatched subcommand is `create`:

```rust
// Determine the active subcommand name for flag injection
let active_sub = if subcommand.is_empty() {
    clap_args.first().map(|s| s.as_str()).unwrap_or("")
} else {
    subcommand
};

// Only inject --recursive for the `create` subcommand, which is the only
// one that declares this flag.
if recursive
    && active_sub == "create"
    && !clap_args.iter().any(|a| a == "--recursive" || a == "-r")
{
    clap_args.push("--recursive".to_string());
}
```

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: src/commands/worktree/mod.rs
Line: 59-69

Comment:
**Injection before empty-args guard bypasses help display**

The `--recursive` injection executes before the `clap_args.is_empty()` guard. If a user runs `meta --recursive git worktree` (no subcommand) the injection turns the empty vec into `["--recursive"]`, the `is_empty()` branch is never reached, and clap returns a cryptic "required argument missing" error instead of the intended help text.

Moving the empty check before the injection would preserve the clean help path:

```rust
// No subcommand at all — show help (check before flag injection)
if clap_args.is_empty() {
    print_worktree_help();
    return CommandResult::Message(String::new());
}

if recursive && !clap_args.iter().any(|a| a == "--recursive" || a == "-r") {
    clap_args.push("--recursive".to_string());
}
```

How can I resolve this? If you propose a fix, please make it concise.

Reviews (1): Last reviewed commit: "fix: thread recursive option from plugin..." | Re-trigger Greptile

Comment thread src/commands/worktree/mod.rs

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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 the current code and only fix it if needed.

Inline comments:
In `@src/commands/worktree/mod.rs`:
- Around line 59-63: The code currently reinjects "--recursive" whenever
recursive is true, regardless of which worktree subcommand is being invoked;
restrict this insertion to only the create subcommand by checking the target
subcommand before mutating clap_args. Concretely: when evaluating whether to
push "--recursive" (the existing recursive && !clap_args.iter().any(...)
branch), also verify that the invocation is for "create" (e.g., check the
subcommand name in whatever variable holds the requested subcommand or check
clap_args for "create") and only then push to clap_args; keep the existing
duplicate-check logic intact.
🪄 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: 596e4821-000e-47b5-9a75-18979a621a6c

📥 Commits

Reviewing files that changed from the base of the PR and between 66ccd5a and ce1c86e.

📒 Files selected for processing (3)
  • .github/workflows/notify-parent.yml
  • src/commands/worktree/mod.rs
  • src/lib.rs

Comment thread src/commands/worktree/mod.rs
Only `create` declares the --recursive flag. Injecting it for all
worktree subcommands (list, status, remove, etc.) would cause clap
parse errors when global --recursive is set.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@mateodelnorte
mateodelnorte merged commit 32a0724 into main Mar 29, 2026
7 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.

1 participant