Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
71 changes: 28 additions & 43 deletions .claude/commands/night-watch-pr-reviewer.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,9 @@ You are the Night Watch PR Reviewer agent. Your job is to check open PRs for thr

## Context

The repo has two GitHub Actions workflows that run on PRs:

- **`.github/workflows/pr-review.yml`** -- AI review that posts a score (0-100) as a comment.
- **`.github/workflows/ci.yml`** -- CI pipeline with jobs: `typecheck`, `lint`, `test`, `build`, and `verify`.
The repo can have multiple PR checks/workflows (project CI plus Night Watch automation jobs).
Common examples include `typecheck`, `lint`, `test`, `build`, `verify`, `executor`, `qa`, and `audit`.
Treat `gh pr checks <number> --json name,state,conclusion` as the source of truth for which checks failed.

A PR needs attention if **any** of the following: merge conflicts present, review score below 80, or any CI job failed.

Expand All @@ -22,15 +21,6 @@ A PR needs attention if **any** of the following: merge conflicts present, revie

## Instructions

0. **Clean up stale review worktrees** from previous interrupted runs before doing anything:

```bash
git worktree list --porcelain | grep '^worktree ' | awk '{print $2}' | grep -- '-nw-review-' | while read -r wt; do
git worktree remove --force "$wt" 2>/dev/null || true
done
git worktree prune
```

1. **Find open PRs** created by Night Watch:

```
Expand Down Expand Up @@ -98,24 +88,18 @@ Parse the review score from the comment body. Look for patterns like:

4. **Fix the PR**:

a. **Check out the PR branch**:
a. **Use the current runner worktree** and check out the PR branch (do **not** create additional worktrees):

```
git fetch origin
git checkout <branch-name>
git pull origin <branch-name>
```

b. **Create a worktree** for the fixes. Branch names may contain `/` (e.g. `night-watch/feature`), so sanitize by replacing `/` with `-` for the directory path:

```bash
SAFE_NAME="$(echo '<branch-name>' | tr '/' '-')"
git worktree add "../night-watch-cli-nw-review-${SAFE_NAME}" <branch-name>
```

`cd` into worktree, run package install (npm install, yarn install, or pnpm install as appropriate).
The reviewer cron wrapper already runs you inside an isolated worktree and performs cleanup.
Stay in the current directory and run package install (npm install, yarn install, or pnpm install as appropriate).

c. **Resolve merge conflicts** (if `mergeStateStatus` was `DIRTY` or `CONFLICTING`):
b. **Resolve merge conflicts** (if `mergeStateStatus` was `DIRTY` or `CONFLICTING`):
- Get the base branch: `gh pr view <number> --json baseRefName --jq '.baseRefName'`
- Rebase the PR branch onto the latest base branch:
```
Expand All @@ -131,7 +115,7 @@ Parse the review score from the comment body. Look for patterns like:
- Push the clean branch: `git push --force-with-lease origin <branch-name>`
- **Do NOT leave any conflict markers (`<<<<<<<`, `=======`, `>>>>>>>`) in any file.**

d. **Address review feedback** (if score < 80):
c. **Address review feedback** (if score < 80):
- Read the review comments carefully. Extract areas for improvement, bugs found, issues found, and specific file/line suggestions.
- For each review suggestion:
- If you agree, implement the change.
Expand All @@ -142,22 +126,29 @@ Parse the review score from the comment body. Look for patterns like:
- Refactor code if structure was criticized.
- Follow all project conventions from CLAUDE.md or similar documentation files.

e. **Address CI failures** (if any):
d. **Address CI failures** (if any):
- Check CI status and identify non-passing checks:
```
gh pr checks <number> --json name,state,conclusion
```
- First enumerate all checks/jobs from GitHub (source of truth):
```
gh pr checks <number> --json name,state,conclusion --jq '.[] | [.name, .state, .conclusion] | @tsv'
```
- To inspect the latest workflow run's job list in detail:
```
RUN_ID=$(gh run list --branch <branch-name> --limit 1 --json databaseId --jq '.[0].databaseId')
gh run view "${RUN_ID}" --json jobs --jq '.jobs[] | [.name, .status, .conclusion] | @tsv'
gh run view "${RUN_ID}" --log-failed
```
- Read the failed job logs carefully to understand the root cause.
- **typecheck failures**: Fix TypeScript type errors.
- **lint failures**: Fix ESLint violations.
- **test failures**: Fix broken tests or update tests to match code changes.
- **build failures**: Fix compilation/bundling errors.
- **verify failures**: This runs after all others -- usually means one of the above needs fixing.
- Fix checks based on their actual names and errors (for example: `typecheck`, `lint`, `test`, `build`, `verify`, `executor`, `qa`, `audit`).
- Do not assume only a fixed set of CI job names.
- Re-run local equivalents of the failing jobs before pushing to confirm the CI issues are fixed.

f. **Run verification**: Run the project's test/lint commands (e.g., `npm test`, `npm run lint`, `npm run verify` or equivalent). Fix until it passes.
e. **Run verification**: Run the project's test/lint commands (e.g., `npm test`, `npm run lint`, `npm run verify` or equivalent). Fix until it passes.

g. **Commit and push** the fixes (only if there are staged changes beyond the rebase):
f. **Commit and push** the fixes (only if there are staged changes beyond the rebase):

```
git add <files>
Expand All @@ -178,9 +169,9 @@ Parse the review score from the comment body. Look for patterns like:
git push origin <branch-name>
```

Note: if the only change was a conflict-free rebase, the `--force-with-lease` push from step (c) is sufficient -- no extra commit needed.
Note: if the only change was a conflict-free rebase, the `--force-with-lease` push from step (b) is sufficient -- no extra commit needed.

h. **Comment on the PR** summarizing what was addressed:
g. **Comment on the PR** summarizing what was addressed:

```
gh pr comment <number> --body "## Night Watch PR Fix
Expand All @@ -205,15 +196,9 @@ Parse the review score from the comment body. Look for patterns like:
Night Watch PR Reviewer"
```

i. **Clean up worktree**:

```bash
SAFE_NAME="$(echo '<branch-name>' | tr '/' '-')"
git worktree remove --force "../night-watch-cli-nw-review-${SAFE_NAME}"
git worktree prune
```

If the worktree was never created (e.g. skipped PR), this is a no-op — continue without error.
h. **Do not manage worktrees directly**:
- Do **not** run `git worktree add`, `git worktree remove`, or `git worktree prune`.
- The cron wrapper handles worktree lifecycle.

5. **Repeat** for all open PRs that need work.

Expand Down
15 changes: 15 additions & 0 deletions docs/PRDs/migrate-bash-to-typescript.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
4. Delete migrated bash functions and bats tests

**Key decisions:**

- **Batched `find-eligible` command** — internalizes the PRD scanning loop (calls `isInCooldown()`, `isClaimed()` directly instead of N subprocess calls)
- **Git ops via `execFileSync('git', ...)`** — testable via real temp git repos (pattern from `execution-history.test.ts`)
- **Claims stay file-based** — SQLite would be over-engineering for cron-level concurrency
Expand All @@ -38,11 +39,13 @@
### Phase 1: Git Utilities

**Files:**

- `packages/core/src/utils/git-utils.ts` (NEW)
- `packages/core/src/__tests__/utils/git-utils.test.ts` (NEW)
- `packages/core/src/index.ts` (add export)

**Implementation:**

- `getBranchTipTimestamp(projectDir, branch): number | null` — replaces `get_branch_tip_timestamp()`
- `detectDefaultBranch(projectDir): string` — replaces `detect_default_branch()`
- `resolveWorktreeBaseRef(projectDir, defaultBranch): string | null` — replaces `resolve_worktree_base_ref()`
Expand All @@ -55,11 +58,13 @@
### Phase 2: Worktree Management

**Files:**

- `packages/core/src/utils/worktree-manager.ts` (NEW)
- `packages/core/src/__tests__/utils/worktree-manager.test.ts` (NEW)
- `packages/core/src/index.ts` (add export)

**Implementation:**

- `prepareBranchWorktree({ projectDir, worktreeDir, branchName, defaultBranch }): IPrepareWorktreeResult`
- `prepareDetachedWorktree({ projectDir, worktreeDir, defaultBranch }): IPrepareWorktreeResult`
- `cleanupWorktrees(projectDir, scope?): string[]` — returns removed paths
Expand All @@ -71,13 +76,15 @@
### Phase 3: Lock & Claim Management

**Files:**

- `packages/core/src/utils/status-data.ts` (extend with `acquireLock`, `releaseLock`)
- `packages/core/src/utils/claim-manager.ts` (NEW)
- `packages/core/src/__tests__/utils/claim-manager.test.ts` (NEW)
- `packages/core/src/__tests__/utils/status-data.test.ts` (add lock tests)
- `packages/core/src/index.ts` (add export)

**Implementation:**

- `acquireLock(lockPath, pid?): boolean` — extends existing `checkLockFile()`, writes PID
- `releaseLock(lockPath): void`
- `claimPrd(prdDir, prdFile, pid?): void` — writes JSON claim file
Expand All @@ -92,11 +99,13 @@
### Phase 4: PRD Discovery

**Files:**

- `packages/core/src/utils/prd-discovery.ts` (NEW)
- `packages/core/src/__tests__/utils/prd-discovery.test.ts` (NEW)
- `packages/core/src/index.ts` (add export)

**Implementation:**

- `findEligiblePrd({ prdDir, projectDir, maxRuntime, prdPriority? }): string | null`
- Scans PRD files, applies priority ordering
- Calls `isClaimed()` from Phase 3 directly (no subprocess)
Expand All @@ -113,13 +122,15 @@
### Phase 5: Remaining Helpers

**Files:**

- `packages/core/src/utils/log-utils.ts` (NEW)
- `packages/core/src/__tests__/utils/log-utils.test.ts` (NEW)
- `packages/core/src/utils/prd-utils.ts` (add `markPrdDone`)
- `packages/core/src/__tests__/utils/prd-utils.test.ts` (extend)
- `packages/core/src/index.ts` (add export)

**Implementation:**

- `rotateLog(logFile, maxSize?): boolean` — replaces `rotate_log()`
- `checkRateLimited(logFile, startLine?): boolean` — replaces `check_rate_limited()`
- `markPrdDone(prdDir, prdFile): boolean` — replaces `mark_prd_done()`
Expand All @@ -129,11 +140,13 @@
### Phase 6: CLI Subcommands

**Files:**

- `packages/cli/src/commands/cron.ts` (NEW)
- `packages/cli/src/__tests__/commands/cron.test.ts` (NEW)
- `packages/cli/src/cli.ts` (register `cronCommand`)

**Subcommands** (following `history.ts` exit-code signaling pattern):

```
cron detect-branch [projectDir] → stdout: branch name
cron acquire-lock <lockFile> → exit 0=acquired, 1=locked
Expand All @@ -155,6 +168,7 @@ cron rotate-log <logFile> → exit 0=rotated
Replace `source night-watch-helpers.sh` function calls with `"${NW_CLI}" cron <subcommand>` calls.

**Order** (simplest to most complex):

1. `night-watch-slicer-cron.sh` — only uses `rotate_log`, `acquire_lock`
2. `night-watch-audit-cron.sh` — adds `detect_default_branch`, worktrees
3. `night-watch-qa-cron.sh` — similar to audit
Expand Down Expand Up @@ -191,6 +205,7 @@ Phases 1, 2, 3, 5 can run in parallel. Phase 4 depends on Phase 3. Phase 6 depen
## Verification

After each phase:

1. `yarn verify` (typecheck + lint)
2. `yarn test` for changed packages
3. Phase 6: test CLI subcommands via `node dist/cli.js cron <cmd>` with temp dirs
Expand Down
Loading
Loading