Skip to content

fix: repair broken WorktreeCreate hook and add PR approval policy#441

Merged
rhuanbarreto merged 4 commits into
mainfrom
fix/worktree-hook-and-approval-policy
Jul 1, 2026
Merged

fix: repair broken WorktreeCreate hook and add PR approval policy#441
rhuanbarreto merged 4 commits into
mainfrom
fix/worktree-hook-and-approval-policy

Conversation

@rhuanbarreto

Copy link
Copy Markdown
Contributor

Summary

  • Fixes the hooks.WorktreeCreate command in .claude/settings.json, which only ran bun install. Once a WorktreeCreate hook is configured, the Claude Code harness defers the entire worktree creation to it and expects only the resulting absolute path on stdout — the old hook did neither, so EnterWorktree failed with errors like path contains control characters or an ENOENT chdir into stray bun install output. (21 stale empty directories under .claude/worktrees/ plus orphaned claude/* branches were leftover evidence of this having been broken for a while.)
  • The fixed hook parses the requested worktree name from the stdin JSON payload, runs git worktree add, installs deps silently, and echoes only the resulting path. Verified end-to-end via EnterWorktree/ExitWorktree — worktree created with full content + node_modules, session cwd matched, clean removal.
  • Documents the hook contract in CLAUDE.md so it doesn't regress back to a bare bun install.
  • Adds APPROVAL_POLICY.md, read by this repo's "Archgate CLI Approver" Cursor Automation (confirmed via its own PR comments — it's custom logic in that automation's prompt, not a documented Cursor platform feature). Per Cursor's Bugbot docs, a success check conclusion already means "no issues found, and no unresolved comments" — Bugbot does not always leave a review comment. The automation's prior fallback logic treated a clean pass with no comment as an unverified signal and withheld approval (see PR #439). The policy clarifies that the check's own conclusion is sufficient on its own, while still requiring human review when the check is missing/pending/failed or Bugbot left unresolved comments.
  • Session findings captured in agent memory (.claude/agent-memory/archgate-developer/) for future reference.

Test plan

  • bun run src/cli.ts check — 39/39 ADR rules pass
  • bun run validate — full pipeline (lint, typecheck, format, 1310 tests, ADR check, knip, build check) passes
  • oxfmt --check . — clean
  • @reviewer skill — APPROVED, 0 violations/warnings across General/Process, Distribution, and General domains
  • Live end-to-end verification of the fixed WorktreeCreate hook via EnterWorktree/ExitWorktree
  • Watch this PR's own "Archgate CLI Approver" comment to confirm it now picks up APPROVAL_POLICY.md (unverified — the automation's policy-file lookup is self-reported, not independently confirmed)

The .claude/settings.json WorktreeCreate hook only ran `bun install`,
which is not enough to satisfy the harness's hook contract: once a
WorktreeCreate hook is configured, the harness defers the entire
worktree creation to it and expects only the resulting absolute path
on stdout. The old hook never created a worktree or emitted a path,
so EnterWorktree failed with errors like "path contains control
characters" or an ENOENT chdir into stray bun install output.
21 stale empty directories under .claude/worktrees/ plus orphaned
claude/* branches were leftover evidence of this.

Fixed the hook to parse the requested name from stdin JSON, run
`git worktree add`, install deps silently, and echo only the
resulting path. Verified end-to-end via EnterWorktree/ExitWorktree.
Documented the hook contract in CLAUDE.md so it doesn't regress.

Also adds APPROVAL_POLICY.md, read by the repo's "Archgate CLI
Approver" Cursor Automation. Per Cursor's Bugbot docs, a `success`
check conclusion already means "no issues found, no unresolved
comments" -- Bugbot does not always leave a comment. The automation's
prior fallback logic treated a clean pass with no comment as an
unverified signal and withheld approval (see PR #439). The policy
clarifies that the check's own conclusion is sufficient on its own.

Session findings captured in agent memory for future reference.

Signed-off-by: Rhuan Barreto <rhuan@barreto.work>
@coderabbitai

coderabbitai Bot commented Jul 1, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@rhuanbarreto, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 3 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: bbf3ceb9-76f3-4f69-a383-0b0fe02fe74c

📥 Commits

Reviewing files that changed from the base of the PR and between ed92b2b and da69664.

📒 Files selected for processing (6)
  • .claude/agent-memory/archgate-developer/MEMORY.md
  • .claude/agent-memory/archgate-developer/project_worktree_create_hook_contract.md
  • .claude/agent-memory/archgate-developer/reference_cursor_approval_agent.md
  • .claude/settings.json
  • APPROVAL_POLICY.md
  • CLAUDE.md

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Comment thread .claude/settings.json Outdated
Comment thread .claude/settings.json Outdated
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jul 1, 2026

Copy link
Copy Markdown

Deploying archgate-cli with  Cloudflare Pages  Cloudflare Pages

Latest commit: da69664
Status: ✅  Deploy successful!
Preview URL: https://b29a3177.archgate-cli.pages.dev
Branch Preview URL: https://fix-worktree-hook-and-approv.archgate-cli.pages.dev

View logs

@cursor cursor 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.

Stale comment

Not approving: Cursor Bugbot completed with a skipping status and reported 2 unresolved medium-severity issues in the WorktreeCreate hook (.claude/settings.json). Human review is needed to address the stale-directory and Windows CRLF findings before merge; no reviewers were assigned.

Open in Web View Automation 

Sent by Cursor Approval Agent: Archgate CLI Approver

@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Code Coverage

Metric Value
Lines 90.0% (6936 / 7709)
Threshold 90% minimum — met
Platforms Linux + Windows

Full HTML report available in workflow artifacts.

Per-directory breakdown
Directory Coverage Lines
src/commands/ 88.1% 1874 / 2128
src/engine/ 90.9% 1463 / 1610
src/formats/ 100.0% 142 / 142
src/helpers/ 90.3% 3457 / 3829

Two issues flagged by Cursor Bugbot on this PR, both reproduced before
fixing:

- The hook only ran `git worktree add` when the target path was
  missing, so a pre-existing stale/empty directory under
  .claude/worktrees/ (exactly the kind of leftover this PR documents
  finding 21 of) would be skipped, cd'd into, and still reported as
  success with no real checkout. Now removes non-worktree leftovers
  (no .git) before the create-if-missing check.
- `jq -r` can emit CRLF on Windows Git Bash; command substitution only
  strips the trailing \n, leaving a stray \r in the parsed name and
  therefore the final stdout path -- reproducing the exact "path
  contains control characters" failure this PR set out to fix. Now
  strips \r from the parsed name.

Signed-off-by: Rhuan Barreto <rhuan@barreto.work>
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 1, 2026
Comment thread .claude/settings.json Outdated

@cursor cursor 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.

Stale comment

Not approving: Cursor Bugbot completed with a skipping status and reported one unresolved medium-severity issue (silent bun install failure in the WorktreeCreate hook). Human review is needed before merge; recommend @rhuanbarreto address or resolve the Bugbot finding.

Open in Web View Automation 

Sent by Cursor Approval Agent: Archgate CLI Approver

…wallowing them

Cursor Bugbot flagged that a failed `bun install --silent` in the
WorktreeCreate hook went unchecked, so the hook always exited 0 and
the harness treated setup as fully successful even with node_modules
missing. Reproduced by corrupting package.json in a fresh worktree
and confirming exit 0 despite bun's own parse error.

Deliberately did not hard-fail here the way `git worktree add` does:
by this point the worktree already exists and may be a *reused*
existing one with real uncommitted work, not just a fresh checkout.
Hard-failing without cleanup would orphan directories again (the
bug fixed two commits ago); adding cleanup risks deleting real work
on a transient install failure. Instead the hook now prints an
explicit warning to stderr on failure, so the condition is visible
rather than silently swallowed, while still completing successfully
since a worktree without deps is still usable.

Signed-off-by: Rhuan Barreto <rhuan@barreto.work>
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 1, 2026

@cursor cursor 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.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit c14e9d6. Configure here.

Comment thread .claude/settings.json Outdated

@cursor cursor 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.

Stale comment

Not approving: Cursor Bugbot completed with a skipping status and reported one unresolved medium-severity finding (missing git worktree prune before add). This PR also introduces a new APPROVAL_POLICY.md with no base-branch version, which requires human review. Recommend @rhuanbarreto address or resolve the Bugbot finding before merge.

Open in Web View Automation 

Sent by Cursor Approval Agent: Archgate CLI Approver

Cursor Bugbot flagged that WorktreeCreate never ran `git worktree
prune` before `git worktree add`. If a worktree's directory was ever
removed without going through `git worktree remove` (crash, manual
rm -rf), git still has it registered internally and `add` fails
outright with "fatal: '<branch>' is already used by worktree at
'<path>'" -- even though the directory is gone, blocking
EnterWorktree until manual cleanup. The round-2 stale-dir check
doesn't catch this case either, since it only fires when the
directory exists but lacks .git; here the directory doesn't exist
at all, only git's internal registration does.

Reproduced by creating a worktree, rm -rf'ing just the directory,
and re-running the hook with the same name -- confirmed the exact
fatal error. Fixed with `git worktree prune` immediately before
`add`; cheap and safe to run unconditionally. Regression-tested
against the earlier stale-dir fix and the plain happy path.

Signed-off-by: Rhuan Barreto <rhuan@barreto.work>

@cursor cursor 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.

Not approving: Cursor Bugbot passed with all prior findings resolved, but this PR introduces a new APPROVAL_POLICY.md with no base-branch version, which requires human review before merge. Recommend @rhuanbarreto confirm the policy wording; no reviewers were assigned.

Open in Web View Automation 

Sent by Cursor Approval Agent: Archgate CLI Approver

@rhuanbarreto rhuanbarreto merged commit de5e97d into main Jul 1, 2026
21 checks passed
@rhuanbarreto rhuanbarreto deleted the fix/worktree-hook-and-approval-policy branch July 1, 2026 15:01
@archgatebot archgatebot Bot mentioned this pull request Jul 1, 2026
rhuanbarreto pushed a commit that referenced this pull request Jul 3, 2026
# archgate

## [0.46.0](v0.45.7...v0.46.0)
(2026-07-02)

### ⚠ BREAKING CHANGES

* **session-context:** per-editor list/show subcommands; remove --skip
and its false premise (#446)

### Features

* **session-context:** per-editor list/show subcommands; remove --skip
and its false premise
([#446](#446))
([dd96230](dd96230))

### Bug Fixes

* **ci:** read POSTHOG_PROJECT_ID from secrets, not vars, in release
annotation ([#443](#443))
([a53b305](a53b305))
* detect opencode Desktop app installs, not just the CLI
([#439](#439))
([ed92b2b](ed92b2b))
* **hooks:** force bash shell for WorktreeCreate hook on Windows
([#442](#442))
([9da86cf](9da86cf))
* **release:** cap breaking-change bumps to minor while pre-1.0
([#447](#447))
([3df6c91](3df6c91)),
closes [#446](#446)
[#440](#440)
[#440](#440)
[#440](#440)
* repair broken WorktreeCreate hook and add PR approval policy
([#441](#441))
([de5e97d](de5e97d))
* **session-context:** select top-level opencode sessions, add --root
flag ([#445](#445))
([29b13f4](29b13f4))

---
This PR was generated with
[simple-release](https://github.com/TrigenSoftware/simple-release).

<details>
<summary>📄 Cheatsheet</summary>
<br>



You can configure the bot's behavior through a pull request comment
using the `!simple-release/set-options` command.

### Command Format

````md
!simple-release/set-options

```json
{
  "bump": {},
  "publish": {}
}
```
````

### Useful Parameters

#### Bump

| Parameter | Type | Description |
|-----------|------|-------------|
| `version` | `string` | Force set specific version |
| `as` | `'major' \| 'minor' \| 'patch' \| 'prerelease'` | Release type
|
| `prerelease` | `string` | Pre-release identifier (e.g., "alpha",
"beta") |
| `firstRelease` | `boolean` | Whether this is the first release |
| `skip` | `boolean` | Skip version bump |
| `byProject` | `Record<string, object>` | Per-project bump options for
monorepos |

#### Publish

| Parameter | Type | Description |
|-----------|------|-------------|
| `skip` | `boolean` | Skip publishing |
| `access` | `'public' \| 'restricted'` | Package access level |
| `tag` | `string` | Tag for npm publication |

### Usage Examples

#### Force specific version

````md
!simple-release/set-options

```json
{
  "bump": {
    "version": "2.0.0"
  }
}
```
````

#### Force major bump

````md
!simple-release/set-options

```json
{
  "bump": {
    "as": "major"
  }
}
```
````

#### Create alpha pre-release

````md
!simple-release/set-options

```json
{
  "bump": {
    "prerelease": "alpha"
  }
}
```
````

#### Publish with specific access and tag

````md
!simple-release/set-options

```json
{
  "bump": {
    "prerelease": "beta"
  },
  "publish": {
    "access": "public",
    "tag": "beta"
  }
}
```
````

### Access Restrictions

The command can only be used by users with permissions:
- repository owner
- organization member
- collaborator

### Notes

- The last comment with `!simple-release/set-options` command takes
priority
- JSON must be valid, otherwise the command will be ignored
- Parameters apply only to the current release execution
- The command can be updated by editing the comment or adding a new one


</details>

<!--
  Please do not edit this comment.
  simple-release-pull-request: true
  simple-release-branch-from: release
  simple-release-branch-to: main
-->

Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
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