Initial dotfiles repo for Mac and Linux
This commit is contained in:
28
claude/.claude/CLAUDE.md
Normal file
28
claude/.claude/CLAUDE.md
Normal file
@@ -0,0 +1,28 @@
|
||||
# Global Claude Code Instructions
|
||||
|
||||
## Canva Monorepo Workflow
|
||||
|
||||
### Pre-Commit Check (MANDATORY)
|
||||
|
||||
When working in the Canva monorepo (`~/work/canva`), ALWAYS run `taz check` before every `git commit`.
|
||||
|
||||
1. `taz check` (generate, format, lint, and test changed files)
|
||||
2. `git add <files>`
|
||||
3. `git commit`
|
||||
|
||||
Never skip step 1.
|
||||
|
||||
### AI Attribution Policy
|
||||
|
||||
Do NOT add any AI attribution to commits or PRs.
|
||||
|
||||
### Write/Modify Operations - IMPORTANT
|
||||
|
||||
For ANY write or modify operations:
|
||||
1. Show the command first
|
||||
2. Explain what it will do
|
||||
3. Wait for explicit approval before running
|
||||
|
||||
### Additional Instructions
|
||||
|
||||
Rules in `~/.claude/rules/` are auto-generated from `~/.dotfiles/ai-instructions/` at install time.
|
||||
37
claude/.claude/settings.json
Normal file
37
claude/.claude/settings.json
Normal file
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"apiKeyHelper": "/usr/local/bin/otter bedrock-bearer-token",
|
||||
"enabledPlugins": {
|
||||
"otter-tools@otter-marketplace": true
|
||||
},
|
||||
"env": {
|
||||
"ANTHROPIC_API_KEY": "",
|
||||
"ANTHROPIC_BASE_URL": "https://api.anthropic.com",
|
||||
"ANTHROPIC_DEFAULT_HAIKU_MODEL": "global.anthropic.claude-haiku-4-5-20251001-v1:0",
|
||||
"ANTHROPIC_DEFAULT_OPUS_MODEL": "global.anthropic.claude-opus-4-6-v1",
|
||||
"ANTHROPIC_MODEL": "global.anthropic.claude-sonnet-4-6",
|
||||
"AWS_REGION": "ap-southeast-2",
|
||||
"CLAUDE_AGENT_SDK_VERSION": "0.2.51",
|
||||
"CLAUDE_CODE_API_KEY_HELPER_TTL_MS": "60000",
|
||||
"CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "1",
|
||||
"CLAUDE_CODE_EMIT_TOOL_USE_SUMMARIES": "true",
|
||||
"CLAUDE_CODE_ENABLE_ASK_USER_QUESTION_TOOL": "true",
|
||||
"CLAUDE_CODE_ENABLE_TELEMETRY": "1",
|
||||
"CLAUDE_CODE_ENTRYPOINT": "claude-desktop",
|
||||
"CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS": "1",
|
||||
"CLAUDE_CODE_MAX_OUTPUT_TOKENS": "32768",
|
||||
"CLAUDE_CODE_SKIP_BEDROCK_AUTH": "1",
|
||||
"CLAUDE_CODE_SSE_PORT": "40246",
|
||||
"CLAUDE_CODE_USE_BEDROCK": "1",
|
||||
"DISABLE_AUTOUPDATER": "1",
|
||||
"ENABLE_IDE_INTEGRATION": "true",
|
||||
"ENABLE_TOOL_SEARCH": "true",
|
||||
"FORCE_COLOR": "1",
|
||||
"MAX_THINKING_TOKENS": "1024",
|
||||
"MCP_CONNECTION_NONBLOCKING": "true",
|
||||
"OTEL_EXPORTER_OTLP_ENDPOINT": "http://localhost:4317",
|
||||
"OTEL_EXPORTER_OTLP_PROTOCOL": "grpc",
|
||||
"OTEL_LOGS_EXPORTER": "otlp",
|
||||
"OTEL_METRICS_EXPORTER": "otlp"
|
||||
},
|
||||
"model": "opus"
|
||||
}
|
||||
224
claude/.claude/skills/ship-it/SKILL.md
Normal file
224
claude/.claude/skills/ship-it/SKILL.md
Normal file
@@ -0,0 +1,224 @@
|
||||
---
|
||||
name: ship-it
|
||||
description: Get PRs over the line — run tests, fix errors, update visreg, check CI, address review comments, and loop until green.
|
||||
disable-model-invocation: false
|
||||
---
|
||||
|
||||
# Ship It
|
||||
|
||||
Automatically drive one or more PRs to a mergeable state by running local checks, pushing fixes, triggering CI, and addressing review feedback in a loop.
|
||||
|
||||
## Step 0: Discover PRs
|
||||
|
||||
Determine which PRs to process:
|
||||
|
||||
1. Run `gh pr list --author @me --state open --json number,headRefName,baseRefName,title,mergeable,mergeStateStatus` to find all open PRs by the current user.
|
||||
2. Detect **PR trains** — a PR train is a chain where PR2's base branch is PR1's head branch, PR3's base is PR2's head, etc. Build the dependency graph from the `baseRefName`/`headRefName` relationships.
|
||||
3. If the current branch belongs to a train, process the **entire train in order** starting from the bottom (closest to `master`). Fixes to an earlier PR may require rebasing later PRs.
|
||||
4. If the current branch is a standalone PR, process only that PR.
|
||||
5. Present the discovered PR(s) to the user and confirm before proceeding.
|
||||
|
||||
## Step 0b: Check Existing Reviews (per PR)
|
||||
|
||||
Before running any local checks or CI, fetch existing review feedback for each PR using the process in Step 4a. If there are unaddressed comments, handle them per Step 5c/5d **before** proceeding to local validation — there is no point running checks if reviewer feedback will change the code.
|
||||
|
||||
## Step 1: Local Validation (per PR branch)
|
||||
|
||||
Check out the branch for the current PR in the train, then run local validation.
|
||||
|
||||
### 1-pre. Check mergeability and branch staleness
|
||||
|
||||
**Check for merge conflicts first** using the `mergeable` and `mergeStateStatus` fields already fetched in Step 0 (or re-check with `gh pr view <number> --json mergeable,mergeStateStatus`). If the PR is `CONFLICTING`, **rebase immediately** before running any checks or triggering CI — there is no point validating or running CI on a branch that cannot merge.
|
||||
|
||||
Then check staleness:
|
||||
|
||||
```bash
|
||||
git fetch origin master
|
||||
```
|
||||
|
||||
```bash
|
||||
merge_base=$(git merge-base HEAD origin/master)
|
||||
diverged_days=$(( ( $(date +%s) - $(git log -1 --format=%ct "$merge_base") ) / 86400 ))
|
||||
echo "Branch diverged from master ~${diverged_days} days ago"
|
||||
```
|
||||
|
||||
If the branch diverged **more than 4 days ago**, proactively rebase before running any checks — at that age in a fast-moving monorepo, many errors are simply stale-branch artifacts. For fresher branches, note the age and continue; it will inform the triage in Step 5 if errors appear.
|
||||
|
||||
**Use a team of agents to parallelise where possible:**
|
||||
|
||||
### 1a. Run `pnpm fin --silent` (agent 1)
|
||||
|
||||
- This performs formatting, linting, testing, and type-checking on the changeset.
|
||||
- If errors are found, fix them. Common fixes:
|
||||
- Type errors: fix the types directly (never use `@ts-ignore` or `as any`)
|
||||
- Lint errors: apply the suggested fix or refactor
|
||||
- Test failures: investigate and fix the root cause
|
||||
- Formatting: `pnpm fin` auto-fixes most formatting issues
|
||||
- Dependency/import issues: run `taz generate` to regenerate `BUILD.bazel` and `tsconfig.json`
|
||||
- Re-run `pnpm fin --silent` after fixes to confirm they resolve the issue.
|
||||
|
||||
### 1b. Run unit tests for affected areas (agent 2)
|
||||
|
||||
- Identify changed files with `git diff --name-only origin/master...HEAD`.
|
||||
- Run targeted tests: `pnpm test -- --findRelatedTests <changed-files>`.
|
||||
- Fix any test failures.
|
||||
|
||||
### 1c. Visual regression tests (agent 3, if applicable)
|
||||
|
||||
- Check if any changed files have associated `.visreg.jsonc` configs or are UI components with visual tests.
|
||||
- If yes, run `pnpm visreg` with appropriate filters.
|
||||
- If visreg detects diffs (exit code 3), you **must** visually verify before updating hashes. Use the `visreg` skill's inspection steps (hash URLs or Visual Comparison Service via `playwright-cli`).
|
||||
- If you **cannot** visually verify the diffs (e.g. Cloudflare auth blocks image URLs, no browser available), **stop and escalate to the user**. Present the old and new hashes, the Visual Comparison Service URL, and the `canv.am/visreg-hash/<hash>.png` URLs so the user can inspect them. Never assume diffs are intentional without actually seeing them.
|
||||
- Only after visual verification (by you or the user) confirms changes are intentional, update expected images with `pnpm visreg -u`.
|
||||
- If failures are unexpected, investigate and fix the root cause.
|
||||
|
||||
### 1d. Functional/integration tests (agent 4, if applicable)
|
||||
|
||||
- Check if changed files have associated `.func.ts` test files.
|
||||
- If yes, run: `pnpm test:func:ts --browser chrome <test-file>`.
|
||||
- Fix any failures.
|
||||
|
||||
**Wait for all agents to complete before proceeding.**
|
||||
|
||||
## Step 2: Commit, Update PR Description, and Push
|
||||
|
||||
1. Stage all changes: `git add` specific changed files (not `git add -A`).
|
||||
2. Commit with a descriptive message following the `<scope>: <description>` convention.
|
||||
3. **Update the PR description if fixes changed the scope or behavior of the PR:**
|
||||
- Fetch the current PR description: `gh pr view --json body -q .body`.
|
||||
- Review whether the fixes you made materially change what the PR does — e.g. new files added, APIs changed, behavior altered, or test strategy updated.
|
||||
- If yes, update the description using `gh pr edit <number> --body "<updated body>"` to reflect the current state of the PR. Preserve the existing structure (Problem/Solution/Testing sections) and add or revise the relevant parts. Do not rewrite sections unrelated to your changes.
|
||||
- If the fixes were purely mechanical (formatting, lint, minor type fixes) and don't change the PR's intent or scope, skip this step.
|
||||
4. Push to the PR branch. Use `git push --force-with-lease` if the branch has been rebased or amended.
|
||||
5. If this is part of a PR train, after pushing fixes to an earlier PR, rebase all subsequent branches in the train:
|
||||
```
|
||||
git checkout <next-branch>
|
||||
git rebase <previous-branch>
|
||||
git push --force-with-lease
|
||||
```
|
||||
Repeat for each subsequent branch in the train. Resolve any rebase conflicts (consult the user if unsure), then re-validate from Step 1. Track status of each PR in the train using the todo list.
|
||||
|
||||
## Step 3: Trigger CI
|
||||
|
||||
1. Find the PR number: `gh pr view --json number -q .number`.
|
||||
2. Comment on the PR to trigger CI: `gh pr comment <number> --body "@canva-ci-bot test"`.
|
||||
|
||||
## Step 4: Wait for CI and Reviews
|
||||
|
||||
1. On macOS, run `caffeinate -i -t 300 &` to prevent the machine from sleeping. On Linux (devbox), skip this step — headless VMs don't sleep.
|
||||
2. Wait 5 minutes for CI to run and reviewers to respond.
|
||||
3. After waiting, check for results in parallel:
|
||||
|
||||
### 4a. Poll CI status and review comments together
|
||||
|
||||
Check both CI and reviews on every poll cycle — do not wait for CI to finish before looking at reviews:
|
||||
|
||||
1. Run `gh pr checks <number>` to see check status.
|
||||
2. Simultaneously fetch review comments using `gh api repos/Canva/canva/pulls/<NUMBER>/reviews` and `gh api repos/Canva/canva/pulls/<NUMBER>/comments`.
|
||||
3. Categorize any new feedback: code changes requested, questions, nits, approvals. Distinguish between **human reviewers** and **bot reviewers** (see Step 5 for handling differences).
|
||||
4. If CI checks are still running **and** no new review comments need attention, wait 2 minutes and re-poll both (up to 3 additional attempts).
|
||||
5. If new review comments arrive while CI is still running, **proceed to Step 5 immediately** to begin addressing feedback — do not wait for CI to finish first. After addressing the feedback, return here to continue polling CI.
|
||||
6. Collect any CI failure details once checks complete.
|
||||
|
||||
## Step 5: Fix Issues and Resolve Comments
|
||||
|
||||
If CI failures or review comments require changes:
|
||||
|
||||
### 5a. Triage and fix attempts
|
||||
|
||||
Always try to fix errors directly first. Use these signals to inform your diagnosis:
|
||||
|
||||
| Signal | What it suggests |
|
||||
| -------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **"Cannot find module" / "Cannot find name" / missing export** | Master may have renamed or moved a symbol. Check whether the PR's imports need updating. |
|
||||
| **Type errors on interfaces/types the PR didn't modify** | A changed signature on master can cascade. Check `git log origin/master --oneline -- <failing-file>` to see if master changed it recently. |
|
||||
| **BUILD.bazel / tsconfig resolution failures** | Build-graph changes on master (new packages, moved targets) frequently break stale branches. |
|
||||
| **Test/snapshot failures in downstream consumers** | If a failing test imports or renders something your PR changed, that's expected cascading breakage — fix the test/snapshot directly. |
|
||||
| **CI "merge conflict" or "not mergeable" status** | A rebase is required regardless. |
|
||||
|
||||
**Fall back to rebasing** only if you can't find a fix or your fix still errors. Also rebase immediately for merge conflicts.
|
||||
|
||||
1. `git fetch origin master`
|
||||
2. `git rebase origin/master`
|
||||
3. Resolve any conflicts (prefer the PR's intent; consult the user if unsure).
|
||||
4. Go back to **Step 1** and re-validate.
|
||||
5. For PR trains, rebase the entire chain bottom-up.
|
||||
|
||||
### 5b. CI failures
|
||||
|
||||
Read the failing check logs using `bk-get-logs-by-commit` or `bk-get-logs-by-url` MCP tools. Diagnose and fix the root cause.
|
||||
|
||||
### 5c. Human review comments
|
||||
|
||||
- Summarise each piece of review feedback for the user.
|
||||
- **Stop and ask the user to confirm** before making any code changes in response to human review comments. Present what you plan to change and wait for approval.
|
||||
- Only after the user confirms, make the requested code changes and respond to comments.
|
||||
- These take highest priority.
|
||||
|
||||
### 5d. Bot review comments
|
||||
|
||||
Address all bot feedback (`developer-platform-bot`, `chatgpt-codex-connector`, etc.) directly in this PR. Do not silently ignore any bot comment.
|
||||
|
||||
**Deferral** — only defer if the fix adds unnecessary complexity or belongs in a separate PR. When deferring:
|
||||
|
||||
1. Reply to the bot thread explaining why.
|
||||
2. Create a JIRA ticket in **CVCD** via `jira-create` with a summary, link to the comment, and context. Include the ticket key in the reply.
|
||||
|
||||
### 5e. Resolve addressed bot comments only
|
||||
|
||||
After fixing issues raised by **bot reviewers**, mark their corresponding review threads as resolved using the GitHub GraphQL API:
|
||||
|
||||
- Fetch unresolved threads: `gh api graphql -f query='{ repository(owner: "Canva", name: "canva") { pullRequest(number: <NUMBER>) { reviewThreads(first: 50) { nodes { id isResolved comments(first: 1) { nodes { body author { login } } } } } } } }' --jq '.data.repository.pullRequest.reviewThreads.nodes[] | select(.isResolved == false) | {id, author: .comments.nodes[0].author.login}'`
|
||||
- Resolve each thread: `gh api graphql -f query='mutation { resolveReviewThread(input: {threadId: "<THREAD_ID>"}) { thread { isResolved } } }'`
|
||||
- Only resolve threads whose feedback has actually been addressed in the code or was already handled before the review was posted.
|
||||
- Do **not** resolve threads where you replied but did not make the suggested change — leave those open for the author to review.
|
||||
- **Never resolve human reviewer threads.** Even if you made the requested change and responded, leave human threads open for the reviewer to verify and resolve themselves. Only resolve threads authored by bots (`developer-platform-bot`, `chatgpt-codex-connector`, etc.).
|
||||
|
||||
After fixing, go back to **Step 1** and loop.
|
||||
|
||||
## Step 6: Exit Conditions
|
||||
|
||||
**Success:** Before declaring success, do a **final review check** — fetch reviews and comments one more time to catch any feedback that arrived during the last fix cycle. Only if all CI checks pass, no unaddressed review comments remain (confirmed by this final check), and all PRs in the train are green, report the final status to the user.
|
||||
|
||||
**Stop and escalate to the user** if any of these occur:
|
||||
|
||||
- **Same error after 3 fix attempts** — you're likely misdiagnosing the root cause.
|
||||
- **CI failure in code the PR doesn't own** — e.g. a global infra flake, a broken shared pipeline, or a test that also fails on master. Don't try to fix other teams' code. Instead, rebase onto latest master first (the fix may have already landed). If the failure persists after rebasing, escalate.
|
||||
- **Review comment requires a design decision** — the reviewer is asking "should we do X or Y?", not "please fix this." Surface the question, don't pick for the user.
|
||||
- **Merge conflict you can't confidently resolve** — when both sides made intentional changes to the same code and the right resolution isn't obvious.
|
||||
- **Blocked on an external dependency** — e.g. a train PR that needs an earlier PR to land first, or a CI check gated on another service.
|
||||
- **Max 5 full loops (Steps 1→5)** — if you've gone around 5 times and it's still not green, something structural is wrong. Stop and summarise what's still failing.
|
||||
|
||||
## PR Train Handling
|
||||
|
||||
When processing a train of PRs:
|
||||
|
||||
- Always process bottom-up (closest to master first).
|
||||
- After fixing and pushing changes to PR N, rebase PR N+1, N+2, etc. on top.
|
||||
- Run validation on each PR after rebasing — the rebase may introduce new conflicts or failures.
|
||||
- If a rebase conflict occurs, resolve it, then continue validation.
|
||||
- Track the status of each PR in the train using the todo list.
|
||||
|
||||
## Sandbox Environment & Force Push Safety
|
||||
|
||||
This skill runs in a sandboxed environment where `git push --force-with-lease` is required for rebased train branches. To prevent accidental pushes to unrelated branches:
|
||||
|
||||
1. **At the start of Step 0**, after discovering PRs, build an **allowlist** of branch names that belong to the train (or the single standalone PR branch).
|
||||
2. **Before every `git push --force-with-lease`**, verify that the current branch is in the allowlist:
|
||||
```
|
||||
current=$(git branch --show-current)
|
||||
```
|
||||
If `$current` is not in the allowlist, **abort the push and report the error** — never force-push a branch that isn't part of the train.
|
||||
3. **Never force-push `master`, `main`, or any base branch that isn't owned by the train.** If a train's root PR targets `master`, only the train's feature branches get force-pushed — never `master` itself.
|
||||
4. Force-pushing is **expected and safe** for train branches after rebasing. Prefer `--force-with-lease`, but `--force` is also permitted if `--force-with-lease` fails (e.g. due to stale refs in the sandbox).
|
||||
|
||||
## PR Commenting Rules
|
||||
|
||||
- **Always identify as Claude** when posting any comment on a PR. Start PR comments with "🤖 _Claude:_" or similar so reviewers know the comment is AI-generated, not from the user. Including comments responding to bots.
|
||||
- **Never post comments impersonating the user.** Every comment must make clear it was written by Claude, not the PR author.
|
||||
- **CI trigger comments** (e.g. `@canva-ci-bot test`) are mechanical and do not need the Claude prefix.
|
||||
|
||||
## Important Notes
|
||||
|
||||
- Never skip pre-commit hooks (`--no-verify`).
|
||||
- Use `pnpm`, not `yarn` or `npm`.
|
||||
Reference in New Issue
Block a user