From 8cbf8a3b714e87f324c0de93007f27b4c1a34490 Mon Sep 17 00:00:00 2001 From: Tarrence van As Date: Fri, 6 Feb 2026 13:48:04 -0500 Subject: [PATCH 1/2] chore: agentic standards --- .agents/skills/create-a-plan/SKILL.md | 231 ++++++++++++++++++ .agents/skills/create-pr/SKILL.md | 89 +++++++ .agents/skills/create-pr/scripts/poll-pr.sh | 225 +++++++++++++++++ .../create-pr/scripts/pr-body-update.sh | 98 ++++++++ .agents/skills/create-pr/scripts/triage-pr.sh | 112 +++++++++ .claude/skills | 1 + .cursor/skills | 1 + .githooks/pre-commit | 23 ++ .github/workflows/claude-code-review.yml | 30 +++ AGENT.md | 1 + AGENTS.md | 88 +++++++ CLAUDE.legacy.md | 63 +++++ CLAUDE.md | 64 +---- bin/setup-githooks | 13 + 14 files changed, 976 insertions(+), 63 deletions(-) create mode 100644 .agents/skills/create-a-plan/SKILL.md create mode 100644 .agents/skills/create-pr/SKILL.md create mode 100755 .agents/skills/create-pr/scripts/poll-pr.sh create mode 100755 .agents/skills/create-pr/scripts/pr-body-update.sh create mode 100755 .agents/skills/create-pr/scripts/triage-pr.sh create mode 120000 .claude/skills create mode 120000 .cursor/skills create mode 100755 .githooks/pre-commit create mode 100644 .github/workflows/claude-code-review.yml create mode 120000 AGENT.md create mode 100644 AGENTS.md create mode 100644 CLAUDE.legacy.md mode change 100644 => 120000 CLAUDE.md create mode 100755 bin/setup-githooks diff --git a/.agents/skills/create-a-plan/SKILL.md b/.agents/skills/create-a-plan/SKILL.md new file mode 100644 index 0000000..0890aee --- /dev/null +++ b/.agents/skills/create-a-plan/SKILL.md @@ -0,0 +1,231 @@ +--- +name: create-a-plan +description: Conduct a focused technical planning interview to produce an implementable, parallelizable plan or spec with clear dependencies, risks, and open questions. +--- + +# Create a Plan Skill + +This skill runs a structured technical interview to turn a rough idea or an existing spec into a detailed, implementable plan. The output is organized for parallel execution: foundations first, then independent workstreams, then merge and integration. + +## Invocation + +The user will provide one of: +- A path to a spec or plan file (for example: `SPEC.md`, `PLAN.md`, `RFC.md`) +- A rough description of what they want to build +- A feature request or problem statement + +Output is always written to `PLAN.md` in the repo root. + +## Process + +### Phase 0: Preflight + +1. If a file path is provided, read it first and note goals, non-goals, constraints, and gaps. +2. Confirm you will produce `PLAN.md` as the output in the repo root. If `PLAN.md` already exists, update it rather than creating a new file. + +### Phase 1: Discovery + +Summarize what is known, then identify missing details. Focus on: +- Goals and non-goals +- Constraints (time, budget, platform, dependencies) +- Success metrics and acceptance criteria + +### Phase 2: Deep Interview + +Use the `AskUserQuestion` (Claude) and/or `request_user_input` (Codex) tools in rounds. Ask 1-3 questions per round. Each round should go deeper and avoid repeating what is already known. + +CRITICAL RULES: +1. Never ask obvious questions. If the codebase or spec already answers it, do not ask it again. +2. Ask about edge cases and failure modes. +3. Probe for hidden complexity (state transitions, migrations, concurrency). +4. Challenge assumptions when they create risk or ambiguity. +5. Identify parallelization boundaries and serial dependencies. +6. If the user is unsure, propose a default and ask for confirmation. + +Question categories to cover as relevant: +- Technical architecture and data flow +- Data model and state management +- API contracts and versioning +- Caching and invalidation +- Background jobs, retries, and idempotency +- Error handling and recovery +- Observability and debugging +- Performance, scale, and SLAs +- Security, privacy, and compliance +- Integrations and external dependencies +- UX flows, accessibility, and responsiveness +- Rollout, migration, and rollback +- Testing strategy and validation + +### Phase 3: Dependency Analysis + +Identify: +1. Serial dependencies that must complete first +2. Parallel workstreams that can run independently +3. Merge points where work reconvenes + +### Phase 4: Plan Generation + +Write the final plan to `PLAN.md`. Ensure the plan includes concrete verification steps the agent can run end to end. If the user only wants a plan in chat, provide it inline and mention that it would be written to `PLAN.md`. + +## Output Format + +The generated plan MUST follow this structure: + +```markdown +# [Feature Name] Implementation Plan + +## Overview +[2-3 sentence summary of what this implements and why] + +## Goals +- [Explicit goal 1] +- [Explicit goal 2] + +## Non-Goals +- [What this explicitly does NOT do] + +## Assumptions and Constraints +- [Known constraints or assumptions] + +## Requirements + +### Functional +- [Requirement] + +### Non-Functional +- [Performance, reliability, security, compliance] + +## Technical Design + +### Data Model +[Schema changes, new entities, relationships] + +### API Design +[New endpoints, request/response shapes, versioning] + +### Architecture +[System diagram in text or mermaid, component interactions] + +### UX Flow (if applicable) +[Key screens, loading states, error recovery] + +--- + +## Implementation Plan + +### Serial Dependencies (Must Complete First) + +These tasks create foundations that other work depends on. Complete in order. + +#### Phase 0: [Foundation Name] +**Prerequisite for:** All subsequent phases + +| Task | Description | Output | +|------|-------------|--------| +| 0.1 | [Task description] | [Concrete deliverable] | +| 0.2 | [Task description] | [Concrete deliverable] | + +--- + +### Parallel Workstreams + +These workstreams can be executed independently after Phase 0. + +#### Workstream A: [Name] +**Dependencies:** Phase 0 +**Can parallelize with:** Workstreams B, C + +| Task | Description | Output | +|------|-------------|--------| +| A.1 | [Task description] | [Concrete deliverable] | +| A.2 | [Task description] | [Concrete deliverable] | + +#### Workstream B: [Name] +**Dependencies:** Phase 0 +**Can parallelize with:** Workstreams A, C + +| Task | Description | Output | +|------|-------------|--------| +| B.1 | [Task description] | [Concrete deliverable] | + +--- + +### Merge Phase + +After parallel workstreams complete, these tasks integrate the work. + +#### Phase N: Integration +**Dependencies:** Workstreams A, B, C + +| Task | Description | Output | +|------|-------------|--------| +| N.1 | [Integration task] | [Concrete deliverable] | + +--- + +## Testing and Validation + +- [Unit, integration, end-to-end coverage] +- [Manual test plan if needed] + +## Rollout and Migration + +- [Feature flags, staged rollout, migration steps] +- [Rollback plan] + +## Verification Checklist + +- [Exact commands or manual steps the agent can run to verify correctness] +- [Expected outputs or success criteria] + +## Risk Assessment + +| Risk | Likelihood | Impact | Mitigation | +|------|------------|--------|------------| +| [Risk description] | Low/Med/High | Low/Med/High | [Strategy] | + +## Open Questions + +- [ ] [Question that still needs resolution] + +## Decision Log + +| Decision | Rationale | Alternatives Considered | +|----------|-----------|------------------------| +| [Decision made] | [Why] | [What else was considered] | +``` + +## Interview Flow Example + +Round 1: High-Level Architecture +- "The spec mentions a sync engine. Is this push-based (webhooks), pull-based (polling), or event-driven (queue)?" +- "What is the expected data volume and throughput?" + +Round 2: Edge Cases +- "If a batch fails mid-run, do we retry the whole batch or resume from a checkpoint?" +- "What happens when source data is deleted but still referenced downstream?" + +Round 3: Parallelization +- "Can we process different categories independently, or are there cross-category dependencies?" +- "Is there a natural partition key that allows sharding?" + +Round 4: Operational +- "What is the acceptable latency for sync or processing?" +- "How will operators debug failures and what visibility do they need?" + +## Key Behaviors + +1. Persist until the plan is implementable and verifiable by the agent, but avoid user fatigue by batching questions. +2. Challenge vague answers when they affect design decisions. +3. Identify hidden work and operational overhead. +4. Think about the merge and integration steps early. +5. Summarize understanding and confirm before writing the final plan. + +## Completing the Interview + +After sufficient rounds of questions: +1. Summarize your understanding back to the user +2. Confirm the parallelization strategy +3. Write the complete plan to the target file +4. Ask if any sections need refinement diff --git a/.agents/skills/create-pr/SKILL.md b/.agents/skills/create-pr/SKILL.md new file mode 100644 index 0000000..e21e877 --- /dev/null +++ b/.agents/skills/create-pr/SKILL.md @@ -0,0 +1,89 @@ +--- +name: create-pr +description: Create or update a PR from current branch to main, watch CI, and address feedback +--- +The user likes the state of the code. + +There are $`git status --porcelain | wc -l | tr -d ' '` uncommitted changes. +The current branch is $`git branch --show-current`. +The target branch is origin/main. + +$`git rev-parse --abbrev-ref @{upstream} 2>/dev/null && echo "Upstream branch exists." || echo "There is no upstream branch yet."` + +**Existing PR:** $`gh pr view --json number,title,url --jq '"#\(.number): \(.title) - \(.url)"' 2>/dev/null || echo "None"` + +The user requested a PR. + +Follow these exact steps: + +## Phase 1: Review the code + +1. Review test coverage +2. Check for silent failures +3. Verify code comments are accurate +4. Review any new types +5. General code review + +## Phase 2: Create/Update PR + +6. Run `git diff` to review uncommitted changes +7. Commit them. Follow any instructions the user gave you about writing commit messages. +8. Push to origin. +9. Use `git diff origin/main...` to review the full PR diff +10. Check if a PR already exists for this branch: + - **If PR exists**: + - Draft/update the description in a temp file (e.g. `/tmp/pr-body.txt`). + - Update the PR body using the non-deprecated script: + - `./.agents/skills/create-pr/scripts/pr-body-update.sh --file /tmp/pr-body.txt` + - Re-fetch the body with `gh pr view --json body --jq .body` to confirm it changed. + - **If no PR exists**: Use `gh pr create --base main` to create a new PR. Keep the title under 80 characters and the description under five sentences. + +The PR description should summarize ALL commits in the PR, not just the latest changes. + +## Phase 3: Monitor CI and Address Issues + +Note: Keep commands CI-safe and avoid interactive `gh` prompts. Ensure `GH_TOKEN` or `GITHUB_TOKEN` is set in CI. + +11. Watch CI status and feedback using the polling script (instead of running `gh` in a loop): + - Run `./.agents/skills/create-pr/scripts/poll-pr.sh --triage-on-change --exit-when-green` (polls every 30s for 10 mins). + - If checks fail, use `gh pr checks` or `gh run list` to find the failing run id, then: + - Fetch the failed check logs using `gh run view --log-failed` + - Analyze the failure and fix the issue + - Commit and push the fix + - Continue polling until all checks pass + +12. Check for merge conflicts: + - Run `git fetch origin main && git merge origin/main` + - If conflicts exist, resolve them sensibly + - Commit the merge resolution and push + +13. Use the polling script output to notice new reviews and comments (avoid direct polling via `gh`): + - If you need a full snapshot, run `./.agents/skills/create-pr/scripts/triage-pr.sh` once. + - If you need full context after the script reports a new item, fetch details once with `gh pr view --comments` or `gh api ...`. + - **Address feedback**: + - For bot reviews, read the review body and any inline comments carefully + - Address comments that are clearly actionable (bug fixes, typos, simple improvements) + - Skip comments that require design decisions or user input + - For addressed feedback, commit fixes with a message referencing the review/comment + +## Phase 4: Merge and Cleanup + +14. Once CI passes and the PR is approved, ask the user if they want to merge the PR. + +15. If the user confirms, merge the PR: + - Use `gh pr merge --squash --delete-branch` to squash-merge and delete the remote branch + +16. After successful merge, check if we're in a git worktree: + - Run: `[ "$(git rev-parse --git-common-dir)" != "$(git rev-parse --git-dir)" ]` + - **If in a worktree**: Use the ask user question tool (`request_user_input`) to ask if they want to clean up the worktree. If yes, run `wt remove --yes --force` to remove the worktree and local branch, then switch back to the main worktree. + - **If not in a worktree**: Just switch back to main with `git checkout main && git pull` + +## Completion + +Report the final PR status to the user, including: +- PR URL +- CI status (passed/merged) +- Any unresolved review comments that need user attention +- Cleanup status (worktree removed or branch switched) + +If any step fails in a way you cannot resolve, ask the user for help. diff --git a/.agents/skills/create-pr/scripts/poll-pr.sh b/.agents/skills/create-pr/scripts/poll-pr.sh new file mode 100755 index 0000000..12fec49 --- /dev/null +++ b/.agents/skills/create-pr/scripts/poll-pr.sh @@ -0,0 +1,225 @@ +#!/usr/bin/env bash +set -euo pipefail + +interval="${POLL_INTERVAL:-30}" +minutes="${POLL_MINUTES:-10}" +poll_once="${POLL_ONCE:-0}" +pr="" +repo="" +exit_when_green=0 +triage_on_change=0 + +usage() { + cat <<'USAGE' +Usage: poll-pr.sh [--pr ] [--repo ] [--interval ] [--minutes ] [--exit-when-green] [--triage-on-change] + +Polls PR checks, review comments, and conversation comments every 30s for 10 minutes by default. +Environment overrides: POLL_INTERVAL, POLL_MINUTES, POLL_ONCE=1. +USAGE +} + +while [[ $# -gt 0 ]]; do + case "$1" in + --pr) + pr="$2" + shift 2 + ;; + --repo) + repo="$2" + shift 2 + ;; + --interval) + interval="$2" + shift 2 + ;; + --minutes) + minutes="$2" + shift 2 + ;; + --exit-when-green) + exit_when_green=1 + shift 1 + ;; + --triage-on-change) + triage_on_change=1 + shift 1 + ;; + -h|--help) + usage + exit 0 + ;; + *) + echo "Unknown arg: $1" >&2 + usage >&2 + exit 1 + ;; + esac +done + +if [[ -z "$pr" ]]; then + pr="$(gh pr view --json number --jq .number 2>/dev/null || true)" +fi + +if [[ -z "$pr" ]]; then + echo "Could not determine PR number. Use --pr ." >&2 + exit 1 +fi + +if [[ -z "$repo" ]]; then + repo="$(gh repo view --json nameWithOwner --jq .nameWithOwner 2>/dev/null || true)" +fi + +if [[ -z "$repo" ]]; then + echo "Could not determine repo. Use --repo owner/name." >&2 + exit 1 +fi + +if ! [[ "$interval" =~ ^[0-9]+$ && "$minutes" =~ ^[0-9]+$ ]]; then + echo "interval and minutes must be integers." >&2 + exit 1 +fi + +iterations=$(( (minutes * 60) / interval )) +if (( iterations < 1 )); then + iterations=1 +fi +if [[ "$poll_once" == "1" ]]; then + iterations=1 +fi + +echo "Polling PR #$pr in $repo every ${interval}s for ${minutes}m (${iterations} iterations)." + +last_issue_comment_id="" +last_review_comment_id="" +last_review_id="" +last_failed_signature="" + +if ! gh auth status >/dev/null 2>&1; then + if [[ -z "${GITHUB_TOKEN:-}" && -z "${GH_TOKEN:-}" ]]; then + echo "Warning: gh auth not configured (set GH_TOKEN or GITHUB_TOKEN)." + fi +fi + +script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +print_new() { + local kind="$1" + local time="$2" + local user="$3" + local url="$4" + local body="$5" + + echo "New $kind by @$user at $time" + if [[ -n "$body" ]]; then + echo " $body" + fi + if [[ -n "$url" ]]; then + echo " $url" + fi +} + +for i in $(seq 1 "$iterations"); do + now=$(date -u +"%Y-%m-%dT%H:%M:%SZ") + echo "[$now] Poll $i/$iterations" + changed=0 + + checks_counts=$(gh pr checks "$pr" --repo "$repo" --json status,conclusion --jq ' + [length, + (map(select(.status != "COMPLETED")) | length), + (map(select(.conclusion != null and .conclusion != "SUCCESS")) | length), + (map(select(.conclusion == "SUCCESS")) | length) + ] | @tsv + ' 2>/dev/null || true) + if [[ -n "$checks_counts" ]]; then + IFS=$'\t' read -r total pending failed success <<< "$checks_counts" + echo "Checks: total=$total pending=$pending failed=$failed success=$success" + else + echo "Checks: unavailable" + fi + + failed_checks=$(gh pr checks "$pr" --repo "$repo" --json name,conclusion,detailsUrl --jq ' + [.[] | select(.conclusion != null and .conclusion != "SUCCESS") | + "\(.name) (\(.conclusion))\t\(.detailsUrl // \"\")" + ] | .[] + ' 2>/dev/null || true) + failed_signature=$(gh pr checks "$pr" --repo "$repo" --json name,conclusion --jq ' + [.[] | select(.conclusion != null and .conclusion != "SUCCESS") | + "\(.name):\(.conclusion)" + ] | sort | join("|") + ' 2>/dev/null || true) + + if [[ -n "$failed_checks" ]]; then + echo "Failed checks:" + while IFS=$'\t' read -r name url; do + if [[ -n "$name" ]]; then + if [[ -n "$url" ]]; then + echo " - $name $url" + else + echo " - $name" + fi + fi + done <<< "$failed_checks" + fi + if [[ -n "$failed_signature" && "$failed_signature" != "$last_failed_signature" ]]; then + last_failed_signature="$failed_signature" + changed=1 + fi + + issue_line=$(gh api "repos/$repo/issues/$pr/comments?per_page=100" --jq ' + if length == 0 then "" else + (max_by(.created_at)) | "\(.id)\t\(.created_at)\t\(.user.login)\t\(.html_url)\t\(.body | gsub("\\n"; " ") | gsub("\\t"; " ") | .[0:200])" + end + ' 2>/dev/null || true) + if [[ -n "$issue_line" ]]; then + IFS=$'\t' read -r issue_id issue_time issue_user issue_url issue_body <<< "$issue_line" + if [[ "$issue_id" != "$last_issue_comment_id" ]]; then + last_issue_comment_id="$issue_id" + print_new "conversation comment" "$issue_time" "$issue_user" "$issue_url" "$issue_body" + changed=1 + fi + fi + + review_comment_line=$(gh api "repos/$repo/pulls/$pr/comments?per_page=100" --jq ' + if length == 0 then "" else + (max_by(.created_at)) | "\(.id)\t\(.created_at)\t\(.user.login)\t\(.html_url)\t\(.body | gsub("\\n"; " ") | gsub("\\t"; " ") | .[0:200])" + end + ' 2>/dev/null || true) + if [[ -n "$review_comment_line" ]]; then + IFS=$'\t' read -r rc_id rc_time rc_user rc_url rc_body <<< "$review_comment_line" + if [[ "$rc_id" != "$last_review_comment_id" ]]; then + last_review_comment_id="$rc_id" + print_new "inline review comment" "$rc_time" "$rc_user" "$rc_url" "$rc_body" + changed=1 + fi + fi + + review_line=$(gh api "repos/$repo/pulls/$pr/reviews?per_page=100" --jq ' + [ .[] | select(.submitted_at != null) ] | + if length == 0 then "" else + (max_by(.submitted_at)) | "\(.id)\t\(.submitted_at)\t\(.user.login)\t\(.html_url)\t\(.state)\t\(.body | gsub("\\n"; " ") | gsub("\\t"; " ") | .[0:200])" + end + ' 2>/dev/null || true) + if [[ -n "$review_line" ]]; then + IFS=$'\t' read -r r_id r_time r_user r_url r_state r_body <<< "$review_line" + if [[ "$r_id" != "$last_review_id" ]]; then + last_review_id="$r_id" + print_new "review ($r_state)" "$r_time" "$r_user" "$r_url" "$r_body" + changed=1 + fi + fi + + if [[ "$triage_on_change" == "1" && "$changed" == "1" ]]; then + "$script_dir/triage-pr.sh" --pr "$pr" --repo "$repo" || true + fi + + if [[ "$exit_when_green" == "1" && -n "${pending:-}" ]]; then + if (( pending == 0 && failed == 0 && total > 0 )); then + echo "Checks green; exiting early." + break + fi + fi + + if (( i < iterations )); then + sleep "$interval" + fi +done diff --git a/.agents/skills/create-pr/scripts/pr-body-update.sh b/.agents/skills/create-pr/scripts/pr-body-update.sh new file mode 100755 index 0000000..bfbb4ac --- /dev/null +++ b/.agents/skills/create-pr/scripts/pr-body-update.sh @@ -0,0 +1,98 @@ +#!/usr/bin/env bash +set -euo pipefail + +body_file="" +pr="" +repo="" + +usage() { + cat <<'USAGE' +Usage: pr-body-update.sh --file [--pr ] [--repo ] + +Updates a PR body using the GraphQL updatePullRequest mutation and verifies the result. +USAGE +} + +while [[ $# -gt 0 ]]; do + case "$1" in + --file) + body_file="$2" + shift 2 + ;; + --pr) + pr="$2" + shift 2 + ;; + --repo) + repo="$2" + shift 2 + ;; + -h|--help) + usage + exit 0 + ;; + *) + echo "Unknown arg: $1" >&2 + usage >&2 + exit 1 + ;; + esac +done + +if [[ -z "$body_file" ]]; then + echo "--file is required." >&2 + exit 1 +fi + +if [[ ! -f "$body_file" ]]; then + echo "Body file not found: $body_file" >&2 + exit 1 +fi + +if [[ ! -s "$body_file" ]]; then + echo "Body file is empty: $body_file" >&2 + exit 1 +fi + +if [[ -z "$pr" ]]; then + pr="$(gh pr view --json number --jq .number 2>/dev/null || true)" +fi + +if [[ -z "$pr" ]]; then + echo "Could not determine PR number. Use --pr ." >&2 + exit 1 +fi + +if [[ -z "$repo" ]]; then + repo="$(gh repo view --json nameWithOwner --jq .nameWithOwner 2>/dev/null || true)" +fi + +if [[ -z "$repo" ]]; then + echo "Could not determine repo. Use --repo owner/name." >&2 + exit 1 +fi + +pr_id="$(gh pr view "$pr" --repo "$repo" --json id --jq .id 2>/dev/null || true)" +if [[ -z "$pr_id" ]]; then + echo "Could not determine PR id for #$pr in $repo." >&2 + exit 1 +fi + +gh api graphql \ + -f query='mutation($id:ID!,$body:String!){updatePullRequest(input:{pullRequestId:$id, body:$body}){pullRequest{id}}}' \ + -f id="$pr_id" \ + -f body="$(cat "$body_file")" \ + >/dev/null + +updated_body="$(gh pr view "$pr" --repo "$repo" --json body --jq .body 2>/dev/null || true)" +if [[ -z "$updated_body" ]]; then + echo "Failed to fetch updated PR body for #$pr in $repo." >&2 + exit 1 +fi + +if [[ "$updated_body" != "$(cat "$body_file")" ]]; then + echo "PR body mismatch after update." >&2 + exit 1 +fi + +echo "Updated PR #$pr body in $repo." diff --git a/.agents/skills/create-pr/scripts/triage-pr.sh b/.agents/skills/create-pr/scripts/triage-pr.sh new file mode 100755 index 0000000..0731d12 --- /dev/null +++ b/.agents/skills/create-pr/scripts/triage-pr.sh @@ -0,0 +1,112 @@ +#!/usr/bin/env bash +set -euo pipefail + +pr="" +repo="" + +usage() { + cat <<'USAGE' +Usage: triage-pr.sh [--pr ] [--repo ] + +Prints a single-shot summary of CI status, latest review, and latest comments. +USAGE +} + +while [[ $# -gt 0 ]]; do + case "$1" in + --pr) + pr="$2" + shift 2 + ;; + --repo) + repo="$2" + shift 2 + ;; + -h|--help) + usage + exit 0 + ;; + *) + echo "Unknown arg: $1" >&2 + usage >&2 + exit 1 + ;; + esac +done + +if [[ -z "$pr" ]]; then + pr="$(gh pr view --json number --jq .number 2>/dev/null || true)" +fi + +if [[ -z "$pr" ]]; then + echo "Could not determine PR number. Use --pr ." >&2 + exit 1 +fi + +if [[ -z "$repo" ]]; then + repo="$(gh repo view --json nameWithOwner --jq .nameWithOwner 2>/dev/null || true)" +fi + +if [[ -z "$repo" ]]; then + echo "Could not determine repo. Use --repo owner/name." >&2 + exit 1 +fi + +checks_counts=$(gh pr checks "$pr" --repo "$repo" --json status,conclusion --jq ' + [length, + (map(select(.status != "COMPLETED")) | length), + (map(select(.conclusion != null and .conclusion != "SUCCESS")) | length), + (map(select(.conclusion == "SUCCESS")) | length) + ] | @tsv +' 2>/dev/null || true) + +if [[ -n "$checks_counts" ]]; then + IFS=$'\t' read -r total pending failed success <<< "$checks_counts" + echo "CI: total=$total pending=$pending failed=$failed success=$success" +else + echo "CI: unavailable" +fi + +failed_checks=$(gh pr checks "$pr" --repo "$repo" --json name,conclusion,detailsUrl --jq ' + [.[] | select(.conclusion != null and .conclusion != "SUCCESS") | + "\(.name)\t\(.conclusion)\t\(.detailsUrl // \"\")" + ] | .[] +' 2>/dev/null || true) +if [[ -n "$failed_checks" ]]; then + while IFS=$'\t' read -r name conclusion url; do + if [[ -n "$name" ]]; then + echo "FAIL: $name $conclusion $url" + fi + done <<< "$failed_checks" +fi + +review_line=$(gh api "repos/$repo/pulls/$pr/reviews?per_page=100" --jq ' + [ .[] | select(.submitted_at != null) ] | + if length == 0 then "" else + (max_by(.submitted_at)) | "\(.state)\t\(.user.login)\t\(.submitted_at)\t\(.html_url)" + end +' 2>/dev/null || true) +if [[ -n "$review_line" ]]; then + IFS=$'\t' read -r r_state r_user r_time r_url <<< "$review_line" + echo "REVIEW: $r_state $r_user $r_time $r_url" +fi + +issue_line=$(gh api "repos/$repo/issues/$pr/comments?per_page=100" --jq ' + if length == 0 then "" else + (max_by(.created_at)) | "\(.user.login)\t\(.created_at)\t\(.html_url)\t\(.body | gsub("\\n"; " ") | gsub("\\t"; " ") | .[0:200])" + end +' 2>/dev/null || true) +if [[ -n "$issue_line" ]]; then + IFS=$'\t' read -r c_user c_time c_url c_body <<< "$issue_line" + echo "COMMENT: conversation $c_user $c_time $c_url $c_body" +fi + +review_comment_line=$(gh api "repos/$repo/pulls/$pr/comments?per_page=100" --jq ' + if length == 0 then "" else + (max_by(.created_at)) | "\(.user.login)\t\(.created_at)\t\(.html_url)\t\(.body | gsub("\\n"; " ") | gsub("\\t"; " ") | .[0:200])" + end +' 2>/dev/null || true) +if [[ -n "$review_comment_line" ]]; then + IFS=$'\t' read -r rc_user rc_time rc_url rc_body <<< "$review_comment_line" + echo "COMMENT: inline $rc_user $rc_time $rc_url $rc_body" +fi diff --git a/.claude/skills b/.claude/skills new file mode 120000 index 0000000..2b7a412 --- /dev/null +++ b/.claude/skills @@ -0,0 +1 @@ +../.agents/skills \ No newline at end of file diff --git a/.cursor/skills b/.cursor/skills new file mode 120000 index 0000000..2b7a412 --- /dev/null +++ b/.cursor/skills @@ -0,0 +1 @@ +../.agents/skills \ No newline at end of file diff --git a/.githooks/pre-commit b/.githooks/pre-commit new file mode 100755 index 0000000..6ea1afd --- /dev/null +++ b/.githooks/pre-commit @@ -0,0 +1,23 @@ +#!/usr/bin/env bash +set -euo pipefail + +STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACMRT) + +if [[ -z "$STAGED_FILES" ]]; then + exit 0 +fi + +# Node (.) +NODE_FILES="$STAGED_FILES" +if echo "$NODE_FILES" | grep -qE '\.(ts|tsx|js|jsx|json|css|scss|yml|yaml)$|^package\.json$|^pnpm-lock\.yaml$|^bun\.lockb?$|^biome\.json$|^tsconfig\..*\.json$'; then + echo 'Running Node checks (.)...' + pnpm run build + + if ! git diff --quiet; then + echo 'Pre-commit modified files (likely formatting). Stage the changes and retry.' + git diff --name-only + exit 1 + fi +fi + +echo 'Pre-commit checks complete.' diff --git a/.github/workflows/claude-code-review.yml b/.github/workflows/claude-code-review.yml new file mode 100644 index 0000000..5593735 --- /dev/null +++ b/.github/workflows/claude-code-review.yml @@ -0,0 +1,30 @@ +name: Claude Code Review + +on: + pull_request: + types: [opened, synchronize, reopened, ready_for_review] + +permissions: + contents: read + pull-requests: write + issues: read + + id-token: write +jobs: + claude-code-review: + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Claude Review + uses: anthropics/claude-code-action@v1 + with: + anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} + prompt: "/review" + # CLAUDE.md is a symlink to AGENTS.md in this repo; keep repo rules there. + claude_args: | + --max-turns 4 diff --git a/AGENT.md b/AGENT.md new file mode 120000 index 0000000..47dc3e3 --- /dev/null +++ b/AGENT.md @@ -0,0 +1 @@ +AGENTS.md \ No newline at end of file diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..f6fded1 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,88 @@ +# Repository Guidelines + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Development Commands + +```bash +# Start development server +pnpm dev + +# Build for production +pnpm build + +# Preview built site +pnpm preview +``` + +Note: This documentation repository is separate from the main controller repository. For controller development commands including `pnpm dev:live` (production API testing mode), refer to the main controller repository's CLAUDE.md file. + +## Project Architecture + +This is a Vocs-based documentation site for Cartridge - a high-performance infrastructure platform for provable games and applications. The project structure is: + +### Core Components +- **Vocs Framework**: Static site generator optimized for documentation +- **React Components**: Custom components like `Homepage.tsx` for landing page +- **Markdown/MDX Pages**: Documentation content in `src/pages/` + +### Content Organization +The documentation covers three main products: + +1. **Controller** (`/controller/*`): Gaming-focused smart contract wallet with session keys, passkey support, paymaster functionality, achievements system, and inventory management +2. **Slot** (`/slot/*`): Horizontally scalable execution sharding platform with vRNG (Verifiable Random Number Generator) support +3. **Arcade** (`/arcade/*`): Central hub connecting players and onchain games + +### Key Configuration +- `vocs.config.ts`: Main configuration with separate sidebars for each product section +- Uses dark theme with custom color scheme (#ffc52a accent, #0c0c0c background) +- GitHub integration for edit links and social links +- Banner component for community engagement + +### Styling & Assets +- Tailwind CSS configuration in `tailwind.config.cjs` +- SVG icons in `src/public/` loaded via vite-plugin-svgr +- Custom CSS variables defined in vocs theme configuration + +### Package Management +- Uses pnpm as package manager +- Key dependencies: React 18, Starknet libraries, Cartridge connector +- Vocs alpha version (1.0.0-alpha.55) + +### TypeScript Twoslash Integration +The documentation site supports TypeScript Twoslash for enhanced code blocks that provide: +- Type information on hover +- IntelliSense-like features +- Compile-time error checking in documentation + +To use Twoslash in code blocks, add `twoslash` to the language identifier: +```typescript twoslash +// Your TypeScript code here with full type checking +``` + +When editing content, maintain the existing markdown structure and follow the established sidebar navigation patterns in `vocs.config.ts`. + +## Agent Tooling + +- **Pre-commit hooks:** run `bin/setup-githooks` (configures `core.hooksPath` for this repo). + +- **Source of truth:** `.agents/`. +- **Symlinks:** `CLAUDE.md` is a symlink to this file (`AGENTS.md`). Editor/agent configs should symlink skills from `.agents/skills`. +- **Skills install/update:** + +```bash +npm_config_cache=/tmp/npm-cache npx -y skills add https://github.com/cartridge-gg/agents --skill create-pr create-a-plan --agent claude-code cursor -y +``` + +- **Configs:** + - `.agents/skills/` (canonical) + - `.claude/skills` -> `../.agents/skills` + - `.cursor/skills` -> `../.agents/skills` + +## Code Review Invariants + +- No secrets in code or logs. +- Keep diffs small and focused; avoid drive-by refactors. +- Add/adjust tests for behavior changes; keep CI green. +- Prefer check-only commands in CI (`format:check`, `lint:check`) and keep local hooks aligned. +- For Starknet/Cairo/Rust/crypto code: treat input validation, authZ, serialization, and signature/origin checks as **blocking** review items. diff --git a/CLAUDE.legacy.md b/CLAUDE.legacy.md new file mode 100644 index 0000000..5000786 --- /dev/null +++ b/CLAUDE.legacy.md @@ -0,0 +1,63 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Development Commands + +```bash +# Start development server +pnpm dev + +# Build for production +pnpm build + +# Preview built site +pnpm preview +``` + +Note: This documentation repository is separate from the main controller repository. For controller development commands including `pnpm dev:live` (production API testing mode), refer to the main controller repository's CLAUDE.md file. + +## Project Architecture + +This is a Vocs-based documentation site for Cartridge - a high-performance infrastructure platform for provable games and applications. The project structure is: + +### Core Components +- **Vocs Framework**: Static site generator optimized for documentation +- **React Components**: Custom components like `Homepage.tsx` for landing page +- **Markdown/MDX Pages**: Documentation content in `src/pages/` + +### Content Organization +The documentation covers three main products: + +1. **Controller** (`/controller/*`): Gaming-focused smart contract wallet with session keys, passkey support, paymaster functionality, achievements system, and inventory management +2. **Slot** (`/slot/*`): Horizontally scalable execution sharding platform with vRNG (Verifiable Random Number Generator) support +3. **Arcade** (`/arcade/*`): Central hub connecting players and onchain games + +### Key Configuration +- `vocs.config.ts`: Main configuration with separate sidebars for each product section +- Uses dark theme with custom color scheme (#ffc52a accent, #0c0c0c background) +- GitHub integration for edit links and social links +- Banner component for community engagement + +### Styling & Assets +- Tailwind CSS configuration in `tailwind.config.cjs` +- SVG icons in `src/public/` loaded via vite-plugin-svgr +- Custom CSS variables defined in vocs theme configuration + +### Package Management +- Uses pnpm as package manager +- Key dependencies: React 18, Starknet libraries, Cartridge connector +- Vocs alpha version (1.0.0-alpha.55) + +### TypeScript Twoslash Integration +The documentation site supports TypeScript Twoslash for enhanced code blocks that provide: +- Type information on hover +- IntelliSense-like features +- Compile-time error checking in documentation + +To use Twoslash in code blocks, add `twoslash` to the language identifier: +```typescript twoslash +// Your TypeScript code here with full type checking +``` + +When editing content, maintain the existing markdown structure and follow the established sidebar navigation patterns in `vocs.config.ts`. diff --git a/CLAUDE.md b/CLAUDE.md deleted file mode 100644 index 5000786..0000000 --- a/CLAUDE.md +++ /dev/null @@ -1,63 +0,0 @@ -# CLAUDE.md - -This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. - -## Development Commands - -```bash -# Start development server -pnpm dev - -# Build for production -pnpm build - -# Preview built site -pnpm preview -``` - -Note: This documentation repository is separate from the main controller repository. For controller development commands including `pnpm dev:live` (production API testing mode), refer to the main controller repository's CLAUDE.md file. - -## Project Architecture - -This is a Vocs-based documentation site for Cartridge - a high-performance infrastructure platform for provable games and applications. The project structure is: - -### Core Components -- **Vocs Framework**: Static site generator optimized for documentation -- **React Components**: Custom components like `Homepage.tsx` for landing page -- **Markdown/MDX Pages**: Documentation content in `src/pages/` - -### Content Organization -The documentation covers three main products: - -1. **Controller** (`/controller/*`): Gaming-focused smart contract wallet with session keys, passkey support, paymaster functionality, achievements system, and inventory management -2. **Slot** (`/slot/*`): Horizontally scalable execution sharding platform with vRNG (Verifiable Random Number Generator) support -3. **Arcade** (`/arcade/*`): Central hub connecting players and onchain games - -### Key Configuration -- `vocs.config.ts`: Main configuration with separate sidebars for each product section -- Uses dark theme with custom color scheme (#ffc52a accent, #0c0c0c background) -- GitHub integration for edit links and social links -- Banner component for community engagement - -### Styling & Assets -- Tailwind CSS configuration in `tailwind.config.cjs` -- SVG icons in `src/public/` loaded via vite-plugin-svgr -- Custom CSS variables defined in vocs theme configuration - -### Package Management -- Uses pnpm as package manager -- Key dependencies: React 18, Starknet libraries, Cartridge connector -- Vocs alpha version (1.0.0-alpha.55) - -### TypeScript Twoslash Integration -The documentation site supports TypeScript Twoslash for enhanced code blocks that provide: -- Type information on hover -- IntelliSense-like features -- Compile-time error checking in documentation - -To use Twoslash in code blocks, add `twoslash` to the language identifier: -```typescript twoslash -// Your TypeScript code here with full type checking -``` - -When editing content, maintain the existing markdown structure and follow the established sidebar navigation patterns in `vocs.config.ts`. diff --git a/CLAUDE.md b/CLAUDE.md new file mode 120000 index 0000000..47dc3e3 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1 @@ +AGENTS.md \ No newline at end of file diff --git a/bin/setup-githooks b/bin/setup-githooks new file mode 100755 index 0000000..e92bcd4 --- /dev/null +++ b/bin/setup-githooks @@ -0,0 +1,13 @@ +#!/usr/bin/env bash +set -euo pipefail + +ROOT=$(git rev-parse --show-toplevel) +cd "$ROOT" + +if [[ -d .husky ]]; then + git config core.hooksPath .husky + echo "Configured git hooksPath to .husky" +else + git config core.hooksPath .githooks + echo "Configured git hooksPath to .githooks" +fi From 35231c0b9267e8b57f8d287a4a3ed73da4755dc2 Mon Sep 17 00:00:00 2001 From: Tarrence van As Date: Fri, 6 Feb 2026 13:50:57 -0600 Subject: [PATCH 2/2] Delete CLAUDE.legacy.md --- CLAUDE.legacy.md | 63 ------------------------------------------------ 1 file changed, 63 deletions(-) delete mode 100644 CLAUDE.legacy.md diff --git a/CLAUDE.legacy.md b/CLAUDE.legacy.md deleted file mode 100644 index 5000786..0000000 --- a/CLAUDE.legacy.md +++ /dev/null @@ -1,63 +0,0 @@ -# CLAUDE.md - -This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. - -## Development Commands - -```bash -# Start development server -pnpm dev - -# Build for production -pnpm build - -# Preview built site -pnpm preview -``` - -Note: This documentation repository is separate from the main controller repository. For controller development commands including `pnpm dev:live` (production API testing mode), refer to the main controller repository's CLAUDE.md file. - -## Project Architecture - -This is a Vocs-based documentation site for Cartridge - a high-performance infrastructure platform for provable games and applications. The project structure is: - -### Core Components -- **Vocs Framework**: Static site generator optimized for documentation -- **React Components**: Custom components like `Homepage.tsx` for landing page -- **Markdown/MDX Pages**: Documentation content in `src/pages/` - -### Content Organization -The documentation covers three main products: - -1. **Controller** (`/controller/*`): Gaming-focused smart contract wallet with session keys, passkey support, paymaster functionality, achievements system, and inventory management -2. **Slot** (`/slot/*`): Horizontally scalable execution sharding platform with vRNG (Verifiable Random Number Generator) support -3. **Arcade** (`/arcade/*`): Central hub connecting players and onchain games - -### Key Configuration -- `vocs.config.ts`: Main configuration with separate sidebars for each product section -- Uses dark theme with custom color scheme (#ffc52a accent, #0c0c0c background) -- GitHub integration for edit links and social links -- Banner component for community engagement - -### Styling & Assets -- Tailwind CSS configuration in `tailwind.config.cjs` -- SVG icons in `src/public/` loaded via vite-plugin-svgr -- Custom CSS variables defined in vocs theme configuration - -### Package Management -- Uses pnpm as package manager -- Key dependencies: React 18, Starknet libraries, Cartridge connector -- Vocs alpha version (1.0.0-alpha.55) - -### TypeScript Twoslash Integration -The documentation site supports TypeScript Twoslash for enhanced code blocks that provide: -- Type information on hover -- IntelliSense-like features -- Compile-time error checking in documentation - -To use Twoslash in code blocks, add `twoslash` to the language identifier: -```typescript twoslash -// Your TypeScript code here with full type checking -``` - -When editing content, maintain the existing markdown structure and follow the established sidebar navigation patterns in `vocs.config.ts`.