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
1 change: 1 addition & 0 deletions .claude/agent-memory/dev-team-lead/MEMORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ You operate in three modes: `[MODE: spec]`, `[MODE: review]`, `[MODE: commit]`.
- [Sandbox & worktree environment quirks](sandbox-environment.md) — node_modules corruption fixes, shared-package build order, prettier CWD, git index corruption recovery, gh CLI `--json` gap on `pr checks`, wiki submodule git-identity setup
- [Testing patterns (Jest/TS/React)](testing-patterns.md) — ThemeProvider over mocking ThemeContext, JSX.Element typing workaround, dynamic-import timing, matcher misuse, overly-broad absence regexes
- [Code patterns confirmed during review](code-patterns.md) — drizzle-orm `sql.join` availability, intentional CSS cross-imports (AutosaveIndicator)
- [Meta-skill reconciliation (issue #1819)](meta-skill-reconciliation.md) — gh project item-add pattern, CLAUDE.md drifts fast, orchestrator has no trailer, worktree cleanup sequence, count-every-occurrence self-check gap

## See Also

Expand Down
60 changes: 60 additions & 0 deletions .claude/agent-memory/dev-team-lead/meta-skill-reconciliation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
---
name: meta-skill-reconciliation
description: Patterns for auditing/fixing .claude/skills/*.md and CLAUDE.md itself (issue #1819) — gh CLI verification, orchestrator trailer convention, worktree cleanup sequence
metadata:
type: project
---

## `gh project` board-status command

`gh project item-list <N> --owner <o> --query "..."` **does not exist** — `item-list` only takes
`--format/--jq/--limit/--owner/--template`, no `--query`. The correct idempotent pattern (proven
in ~16 real invocations during the 2026-07-06/07 batch-develop session, now the canonical form in
`develop`/`epic-start`/`release` SKILL.md files):

```bash
ITEM_ID=$(gh project item-add 4 --owner steilerDev --url https://github.com/steilerDev/cornerstone/issues/<n> --format json --jq '.id')
gh project item-edit --id "$ITEM_ID" --project-id PVT_kwHOAGtLQM4BOlve --field-id PVTSSF_lAHOAGtLQM4BOlvezg9P0yo --single-select-option-id <option-id>
```

`item-add` is idempotent — if the issue is already on the board it just returns the existing
item's ID, no duplicate is created. Always verify `gh <subcommand> --help` directly rather than
trusting a skill file's existing command — this bug shipped in 3 skills for a while.

## CLAUDE.md drifts fast — verify current state before trusting an issue body's claims

An issue describing a "defect" can predate a fix that already landed. On 2026-07-07 I found the
worktree-removal policy had **already flipped** (PR #1825, merged same day) and a Canonical Agent
Trailers table had **already been added** (PR #1818) — both assumed-stale by the issue I was
fixing. Always `grep`/`Read` the actual current file before writing the fix, don't just diff
against the issue's quoted snippets.

## Orchestrator-authored commits/PRs have no `Co-Authored-By` trailer

CLAUDE.md's Canonical Agent Trailers table lists the 11 named sub-agents only — no `orchestrator`
row. Per the Agent Attribution section ("use that agent's name in the trailer" — implying no
trailer when no agent contributed), orchestrator-only commits (e.g. a `.claude/checklists/`
lessons-learned update) should carry **no** Co-Authored-By line at all. For orchestrator-authored
**PR bodies** specifically (not git trailers), the established precedent — already used correctly
in `fix-e2e` and `dependabot` before this reconciliation — is a `🤖 Generated with [Claude
Code](https://claude.com/claude-code)` footer, not a fabricated `Co-Authored-By: Claude Opus 4.6`
line. Apply this precedent instead of inventing a new convention when you find a stale/fake
trailer.

## Worktree cleanup sequence (post-#1825 policy)

CLAUDE.md's Session Isolation section: remove the worktree **before** deleting the branch, both
from the *base* repository, and force-delete (`-D` not `-d`) because this repo squash-merges to
`beta` — squash history fails `-d`'s ancestry check even for genuinely-merged branches. Capture
`CURRENT_BRANCH`/`WORKTREE_PATH` *before* `cd`-ing to the base repo (`git worktree list
--porcelain | awk '/^worktree/{print $2; exit}'` finds the base repo path from any worktree). This
must be the session's last action — the cwd it started from no longer exists afterward. Any skill
that loops `/develop` as a sub-routine (`batch-develop`, `epic-run`, `release` step 4e) must
explicitly exclude this cleanup mid-loop, or the first loop iteration terminates the whole batch.

## Self-check gap: count *every* occurrence a fix pattern gets applied

When a spec says "apply fix X to every skill that does Y," explicitly enumerate the file list
before writing the verification grep's expected count — I undercounted (said 3, actual was 4)
because I forgot my own spec item added a 4th occurrence (batch-develop's new Session Cleanup
step) beyond the 3 I was tracking from the original bug report's file list.
42 changes: 29 additions & 13 deletions .claude/skills/batch-develop/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
---
name: batch-develop
description: 'Reads /tmp/notes.md and runs /develop for each line sequentially. Each line gets its own branch, PR, and full development cycle. Skips /develop step 1 (Rebase) since it handles its own baseline reset.'
description: 'Reads /tmp/batch-queue.md and runs /develop for each line sequentially. Each line gets its own branch, PR, and full development cycle. Skips /develop step 1 (Rebase) since it handles its own baseline reset.'
---

# Batch Develop — Sequential Development from Notes File

You are the orchestrator running a sequential development pipeline. This skill accepts a list of GitHub issue numbers (as arguments) or reads `/tmp/notes.md`, and invokes the `/develop` workflow for each item, one at a time. Each item gets its own branch, PR, and full development cycle.
You are the orchestrator running a sequential development pipeline. This skill accepts a list of GitHub issue numbers (as arguments) or reads `/tmp/batch-queue.md`, and invokes the `/develop` workflow for each item, one at a time. Each item gets its own branch, PR, and full development cycle.

**When to use:** Processing a backlog of issues or bug descriptions listed in `/tmp/notes.md`, where each item should be developed independently.
**When to use:** Processing a backlog of issues or bug descriptions listed in `/tmp/batch-queue.md`, where each item should be developed independently.
**When NOT to use:** When items should be batched into a single PR (use `/develop @/tmp/notes.md` instead). When running a full epic lifecycle (use `/epic-run`).

## Input

`$ARGUMENTS` determines the input source:

- **Issue list**: `$ARGUMENTS` contains issue numbers (e.g., `#741 #742 #743` or `741, 742, 743` or `#741 #742`). Any combination of `#N` or bare `N` separated by spaces, commas, or semicolons.
- **File mode** (no arguments): When `$ARGUMENTS` is empty, falls back to reading `/tmp/notes.md`. If the file does not exist or is empty, ask the user to provide issue numbers or create the file before proceeding.
- **File mode** (no arguments): When `$ARGUMENTS` is empty, falls back to reading `/tmp/batch-queue.md`. If the file does not exist or is empty, ask the user to provide issue numbers or create the file before proceeding.

### File Format (when using `/tmp/notes.md`)
### File Format (when using `/tmp/batch-queue.md`)

`/tmp/notes.md` contains one item per line:
`/tmp/batch-queue.md` contains one item per line:

- **Issue number**: `#42` or `42`
- **Bug/feature description**: Free-text description
Expand All @@ -32,7 +32,7 @@ Use tasks to track progress across the batch. Tasks survive context compression

**Create these tasks upfront** (using `TaskCreate`):

1. **Read and parse queue** — Parse input arguments or /tmp/notes.md into items queue
1. **Read and parse queue** — Parse input arguments or /tmp/batch-queue.md into items queue
2. **Session setup** — Fetch latest beta, sync wiki

**After parsing** — create one task per item in the queue:
Expand All @@ -53,7 +53,7 @@ Use tasks to track progress across the batch. Tasks survive context compression

**If `$ARGUMENTS` contains issue numbers:** Extract all issue numbers from the arguments (strip `#` prefixes, commas, semicolons). Each number becomes an item in the queue.

**If `$ARGUMENTS` is empty:** Read `/tmp/notes.md`. Parse each non-empty, non-comment line into an ordered **items queue**.
**If `$ARGUMENTS` is empty:** Read `/tmp/batch-queue.md`. Parse each non-empty, non-comment line into an ordered **items queue**.

Print the queue:

Expand Down Expand Up @@ -98,14 +98,14 @@ git checkout -B batch-dev-temp origin/beta

Invoke the `/develop` skill with the current item as `$ARGUMENTS`. The `/develop` skill handles the full cycle (steps 1–11): resolve issue → visual spec → branch → move to in progress → implement + test → verify PR → review → fix loop → merge → close.

**Note:** Skip `/develop` step 1 (Rebase) — the baseline reset is already handled by step 3a above. Execute `/develop` steps 2–11 for each item.
**Note:** Skip `/develop` step 1 (Rebase) — the baseline reset is already handled by step 3a above. Execute `/develop` steps 2–11 for each item, **except step 11's worktree/branch cleanup item** — the batch session must stay in the same worktree to process the next item. Do not let `/develop` run its worktree removal mid-batch; that step only runs once, after the entire queue is processed (see step 5, Session Cleanup, below). Per-item local branches are left in place during the loop rather than individually deleted — this avoids the checkout-conflict fragility of deleting a branch that a subsequent iteration's `git checkout -B` may still be touching, at the cost of leaving a handful of merged local branches for the final cleanup (or a manual `git branch --merged beta` sweep) to catch.

#### 3c. Track Result

After `/develop` completes for the item:

- **Success** (PR merged, issue closed): Add to completed list. If in file mode, remove the line from `/tmp/notes.md`.
- **Failure** (retry budget exhausted or error): Add to failed list, continue to next item. If in file mode, keep the line in `/tmp/notes.md`.
- **Success** (PR merged, issue closed): Add to completed list. If in file mode, remove the line from `/tmp/batch-queue.md`.
- **Failure** (retry budget exhausted or error): Add to failed list, continue to next item. If in file mode, keep the line in `/tmp/batch-queue.md`.

#### 3d. Progress Update

Expand All @@ -125,7 +125,23 @@ Batch Develop Complete
Total items: N
Completed: N — #42, #55, #61
Failed: N — #88 (reason)
Remaining in /tmp/notes.md: N lines
Remaining in /tmp/batch-queue.md: N lines
```

In file mode: if all items succeeded, `/tmp/notes.md` will be empty (or contain only comments). If any failed, the file retains those lines for a future run.
In file mode: if all items succeeded, `/tmp/batch-queue.md` will be empty (or contain only comments). If any failed, the file retains those lines for a future run.

### 5. Session Cleanup

After the batch completes (all items processed, summary printed), clean up the worktree per CLAUDE.md's Session Isolation policy — the batch-deferred equivalent of `/develop` step 11's cleanup item:

```bash
git status --porcelain # must be empty before proceeding
CURRENT_BRANCH=$(git branch --show-current)
WORKTREE_PATH=$(pwd)
BASE_REPO=$(git worktree list --porcelain | awk '/^worktree/{print $2; exit}')
cd "$BASE_REPO"
git worktree remove "$WORKTREE_PATH"
git branch -D "$CURRENT_BRANCH"
```

**Skip this step** if any items in the batch failed and remain unresolved in the queue file, or if the worktree has uncommitted changes — leave it in place for manual follow-up in that case.
10 changes: 3 additions & 7 deletions .claude/skills/dependabot/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -194,17 +194,13 @@ Each agent receives:
- PR number and URL
- The full failed-check excerpt
- The `BREAKING` findings from step 3 (if any)
- Explicit instruction to commit on the current branch (the Dependabot branch) and NOT to push — the orchestrator pushes after committing.
- Explicit instruction to only edit files — per CLAUDE.md's flat delegation model, implementation agents never run `git commit` or `git push` themselves. Staging, committing, and pushing are handled exclusively by `dev-team-lead [MODE: commit]` in step 5d.

#### 5d. Commit & push

Use `dev-team-lead [MODE: commit]` to stage, write the conventional commit message with all contributing agent trailers, and push. Per CLAUDE.md trailer-verification rules, every production-file change must carry the correct `Co-Authored-By` trailer.
Launch `dev-team-lead [MODE: commit]` to stage the changes, write the conventional commit message with all contributing agent trailers, and push — this is the sole commit/push action for this PR; do not run a separate `git push`. Per CLAUDE.md trailer-verification rules, every production-file change must carry the correct `Co-Authored-By` trailer.

```bash
git push
```

(No `-u` — the branch already tracks the Dependabot remote ref.)
This PR already exists (it _is_ the Dependabot PR) — explicitly instruct dev-team-lead to **skip PR creation** in its `[MODE: commit]` protocol (there is no new PR to open) and to push without `-u` (the branch already tracks the Dependabot remote ref).

#### 5e. Wait for CI

Expand Down
47 changes: 27 additions & 20 deletions .claude/skills/develop/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ Move the issue(s) to **In Progress** on the Projects board.
#### Single-item mode

```bash
ITEM_ID=$(gh project item-list 4 --owner steilerDev --format json --limit 1 --query "is:issue #<issue-number>" --jq '.items[0].id')
ITEM_ID=$(gh project item-add 4 --owner steilerDev --url https://github.com/steilerDev/cornerstone/issues/<issue-number> --format json --jq '.id')
gh project item-edit --id "$ITEM_ID" --project-id PVT_kwHOAGtLQM4BOlve --field-id PVTSSF_lAHOAGtLQM4BOlvezg9P0yo --single-select-option-id 296eeabe
```

Expand Down Expand Up @@ -274,10 +274,11 @@ git log origin/beta..HEAD --format="%b"

If production files were changed (`git diff --name-only origin/beta..HEAD | grep -E '^(server|client|shared)/'`), verify the commit body contains the appropriate Co-Authored-By trailers:

- Files under `server/` or `shared/` → must have `Co-Authored-By: Claude backend-developer (Haiku`
- Files under `client/` (except `client/src/i18n/de/` and `client/src/i18n/glossary.json`) → must have `Co-Authored-By: Claude frontend-developer (Haiku`
- Files under `server/` or `shared/`, excluding `*.test.ts`/`*.test.tsx` → must have `Co-Authored-By: Claude backend-developer (Haiku`
- Files under `client/` (except `client/src/i18n/de/`, `client/src/i18n/glossary.json`, and `*.test.ts`/`*.test.tsx`) → must have `Co-Authored-By: Claude frontend-developer (Haiku`
- Files under `client/src/i18n/de/` or `client/src/i18n/glossary.json` → must have `Co-Authored-By: Claude translator (Sonnet`
- Files under `e2e/` → must have `Co-Authored-By: Claude e2e-test-engineer (Sonnet`
- Files matching `*.test.ts` or `*.test.tsx` outside `e2e/` → must have `Co-Authored-By: Claude qa-integration-tester (Sonnet`

If trailers are missing, the dev-team-lead missed an agent in the contributing list. Re-launch `[MODE: commit]` with the corrected list.

Expand All @@ -299,7 +300,7 @@ Fixes #<issue-number>
- [ ] Integration tests pass
- [ ] Pre-commit hook quality gates pass

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code)
EOF
)"
```
Expand Down Expand Up @@ -334,7 +335,7 @@ Fixes #61
- [ ] Integration tests pass
- [ ] Pre-commit hook quality gates pass

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code)
EOF
)"
```
Expand Down Expand Up @@ -430,20 +431,23 @@ After merge:
```
2. Move the issue to **Done** on the Projects board:
```bash
ITEM_ID=$(gh project item-list 4 --owner steilerDev --format json --limit 1 --query "is:issue #<issue-number>" --jq '.items[0].id')
ITEM_ID=$(gh project item-add 4 --owner steilerDev --url https://github.com/steilerDev/cornerstone/issues/<issue-number> --format json --jq '.id')
gh project item-edit --id "$ITEM_ID" --project-id PVT_kwHOAGtLQM4BOlve --field-id PVTSSF_lAHOAGtLQM4BOlvezg9P0yo --single-select-option-id c558f50d
```
3. **Remove resolved line from source file** (only when input was a `@`-prefixed file path):
- Remove the line from the source file that produced the resolved item (matched by original text).
- Preserve comments (`#`-prefixed lines) and empty lines.
4. Clean up the branch:
```
git checkout beta && git pull && git branch -d <branch-name>
```
5. Exit the session and remove the worktree:
```
/exit
4. Clean up the worktree and branch, per CLAUDE.md's Session Isolation policy (only once the PR is merged and the worktree has no uncommitted changes):
```bash
git status --porcelain # must be empty before proceeding
CURRENT_BRANCH=$(git branch --show-current)
WORKTREE_PATH=$(pwd)
BASE_REPO=$(git worktree list --porcelain | awk '/^worktree/{print $2; exit}')
cd "$BASE_REPO"
git worktree remove "$WORKTREE_PATH"
git branch -D "$CURRENT_BRANCH"
```
Use `-D` (force), not `-d` — this repo squash-merges to `beta`, so `-d`'s "fully merged" check will refuse even for genuinely merged branches. This must be the last action of the session (the working directory it started from no longer exists afterward).

#### Multi-item mode

Expand All @@ -456,11 +460,14 @@ After merge:
- For each closed issue, remove the line from the source file that produced it (matched by original text — the issue number or description as it appeared in the file).
- Preserve comments (`#`-prefixed lines) and empty lines that were not part of the resolved items.
- If all non-comment, non-empty lines have been removed, leave the file with only its comments (or empty).
4. Clean up the branch:
```
git checkout beta && git pull && git branch -d <branch-name>
```
5. Exit the session and remove the worktree:
```
/exit
4. Clean up the worktree and branch, per CLAUDE.md's Session Isolation policy (only once the PR is merged and the worktree has no uncommitted changes):
```bash
git status --porcelain # must be empty before proceeding
CURRENT_BRANCH=$(git branch --show-current)
WORKTREE_PATH=$(pwd)
BASE_REPO=$(git worktree list --porcelain | awk '/^worktree/{print $2; exit}')
cd "$BASE_REPO"
git worktree remove "$WORKTREE_PATH"
git branch -D "$CURRENT_BRANCH"
```
Use `-D` (force), not `-d` — this repo squash-merges to `beta`, so `-d`'s "fully merged" check will refuse even for genuinely merged branches. This must be the last action of the session (the working directory it started from no longer exists afterward).
Loading