Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
80 commits
Select commit Hold shift + click to select a range
9bd2854
feat(shared): add Avenia webhook types and subscription API
Sharqiewicz Jul 29, 2026
ec2f838
feat(api): add Resend and Avenia webhook configuration
Sharqiewicz Jul 29, 2026
76722a3
feat(api): add email_notifications table and model
Sharqiewicz Jul 29, 2026
822364f
feat(api): add email notification service with Resend transport
Sharqiewicz Jul 29, 2026
35020bd
feat(api): send ramp completion emails
Sharqiewicz Jul 29, 2026
fb3f258
feat(api): receive Avenia verification webhooks
Sharqiewicz Jul 29, 2026
531a841
feat(api): add notification dispatch and KYB status workers
Sharqiewicz Jul 29, 2026
332991b
chore(api): add email preview and webhook registration scripts
Sharqiewicz Jul 29, 2026
075b6b7
docs: document email notification system
Sharqiewicz Jul 29, 2026
f104bca
fix(api): point email notifications at provider_customers
Sharqiewicz Jul 30, 2026
ddb5ea7
fix(api): make the last notification backoff step reachable
Sharqiewicz Aug 3, 2026
78648b5
fix(api): recover completion emails the inline enqueue never wrote
Sharqiewicz Aug 3, 2026
04183d3
feat(api): re-enable Ethereum onramps
ebma Aug 4, 2026
2c0236a
feat(api): price Ethereum destination gas dynamically
ebma Aug 4, 2026
5bed681
refactor(api): generalize EVM destination gas funding
ebma Aug 5, 2026
ddf0721
fix(api): skip uncollectible direct destination fees
ebma Aug 5, 2026
db293f8
fix(api): name the right verification kind in outcome emails
Sharqiewicz Aug 5, 2026
152e89e
fix(api): poll KYB attempts on their last update, not creation
Sharqiewicz Aug 5, 2026
90b2ea1
fix(api): bound Avenia public key refetches
Sharqiewicz Aug 5, 2026
1eca7da
feat(api): email Alfredpay verification outcomes
Sharqiewicz Aug 5, 2026
876e034
docs: sync email notification and integration specs
Sharqiewicz Aug 5, 2026
f9f5ea0
fix(api): harden EVM destination funding
ebma Aug 5, 2026
934af29
Merge branch 'staging' into feat/email-notifications
Sharqiewicz Aug 6, 2026
8f71fce
fix(api): validate Avenia webhook payloads before reading them
Sharqiewicz Aug 6, 2026
cd83383
fix(api): bound email retries and honour notification opt-outs
Sharqiewicz Aug 6, 2026
5c1f254
docs: sync email notification architecture with dispatch fixes
Sharqiewicz Aug 6, 2026
e17614c
test: cover Avenia webhook registration contract
ebma Aug 6, 2026
d70f8f5
fix(api): harden Avenia webhook verification
ebma Aug 6, 2026
ed8e8b1
fix(api): make Alfredpay outcome polling reliable
ebma Aug 6, 2026
e1deeae
fix(api): coordinate notification background workers
ebma Aug 6, 2026
60c2f68
fix(api): reconcile every missing ramp completion email
ebma Aug 6, 2026
47dfd20
docs: describe notification delivery safeguards
ebma Aug 6, 2026
14a478a
fix(api): renumber email notifications migration and backfill complet…
ebma Aug 6, 2026
f7232b4
fix(api): exclude partner-API ramps from completion emails
ebma Aug 6, 2026
3cb863a
fix(api): trim DECIMAL scale padding from completion email amounts
ebma Aug 6, 2026
f0dbe7d
test(api): restore leaked module mocks and harden the leak canary
ebma Aug 6, 2026
60384ad
test(api): cover the dispatch safety properties left unasserted
ebma Aug 6, 2026
ff318bf
fix(api): keep Alfredpay enqueue failures out of the 404 staleness he…
ebma Aug 6, 2026
1aa7b86
fix(api): stop the KYB poller re-fetching settled attempts
ebma Aug 6, 2026
0634e51
perf(api): skip the locale lookup for duplicate notification enqueues
ebma Aug 6, 2026
6b7c4ff
fix(api): harden webhook intake, auth-mail i18n, and contract cleanup
ebma Aug 6, 2026
7c13e63
docs(repo): move email notification docs to the canonical flat layout
ebma Aug 6, 2026
f82b458
fix(api): log the Alfredpay provider id in the outcome-enqueue error …
ebma Aug 6, 2026
d455f7c
test(api): snapshot modules before mocking so afterAll restores are real
ebma Aug 6, 2026
69e9f08
test(api): snapshot the remaining live-namespace mock restores
ebma Aug 7, 2026
9804a6e
fix(api): enqueue KYB outcomes observed by the attempt-status route
ebma Aug 7, 2026
cd4a86b
fix(api): harden the KYB poller against starvation and mismatched att…
ebma Aug 7, 2026
0f691fb
fix(shared): bound BRLA API requests with a 30s timeout
ebma Aug 7, 2026
6026f96
fix(api): bound the completion email reconcile batch
ebma Aug 7, 2026
de18eaf
docs(repo): repair the spec link and stale migration number
ebma Aug 7, 2026
79cf6dc
Merge pull request #1295 from pendulum-chain/feat/email-notifications
ebma Aug 7, 2026
0b3bed1
feat(api): add AlfredPay quote pricing metadata
ebma Aug 7, 2026
4efc731
feat(dashboard): wire the email notification toggles to preferences
ebma Aug 7, 2026
10443e5
docs(repo): clarify agent and PR title guidance
ebma Aug 7, 2026
71edfe7
fix(shared): initialize crypto before generating ephemeral
ebma Aug 7, 2026
9e8a932
Merge pull request #1323 from pendulum-chain/codex/alfredpay-quote-pr…
ebma Aug 7, 2026
23e4ff5
feat(shared): move the email notification type strings into the wire …
ebma Aug 7, 2026
dc476df
fix(dashboard): honor the master switch and harden preference updates
ebma Aug 7, 2026
cc3aa07
test(api): verify dynamic destination funding
ebma Aug 7, 2026
783de98
Merge pull request #1324 from pendulum-chain/feat/dashboard-notificat…
ebma Aug 7, 2026
b0a627d
chore(repo): merge staging into Ethereum onramp branch
ebma Aug 7, 2026
3a6a661
Merge pull request #1311 from pendulum-chain/codex/enable-ethereum-on…
ebma Aug 7, 2026
b970c84
chore(repo): merge staging into dynamic EVM funding branch
ebma Aug 7, 2026
fedea2f
fix(api): harden dynamic EVM destination funding
ebma Aug 7, 2026
908fb1f
feat(repo): add wire-contract gate for the partner-facing typed surface
ebma Aug 8, 2026
36b504b
chore(repo): add vortex-review and address-feedback agent skills
ebma Aug 8, 2026
4d607b9
chore(repo): add ship pipeline and babysit-pr agent skills
ebma Aug 8, 2026
477660f
fix(repo): expand generics, conditionals, and readonly in wire gate
ebma Aug 10, 2026
aeb0ee3
docs(repo): fix review-comment fetching in pr skills
ebma Aug 10, 2026
92419ad
fix(repo): preserve readonly on index signatures and tuples in gate
ebma Aug 10, 2026
7adc12d
docs(repo): require trusted head before running branch code in skills
ebma Aug 10, 2026
a732fec
Merge pull request #1326 from pendulum-chain/claude/review-workflow-t…
ebma Aug 10, 2026
535e2fc
Merge remote-tracking branch 'origin/staging' into codex/dynamic-evm-…
ebma Aug 10, 2026
96e44da
chore(repo): move agent skills to .agents/skills for all agents
ebma Aug 10, 2026
95efd0f
Merge remote-tracking branch 'origin/staging' into codex/dynamic-evm-…
ebma Aug 10, 2026
268e00b
fix(api): harden dynamic EVM destination funding
ebma Aug 10, 2026
bbf7c8e
fix(api): validate and replay EVM funding operations
ebma Aug 10, 2026
3eb8bae
fix(api): revalidate destination funding presigns
ebma Aug 10, 2026
ef01443
Merge pull request #1312 from pendulum-chain/codex/dynamic-evm-destin…
ebma Aug 10, 2026
999f3ba
docs(api): document quote fee-limit 503 responses
ebma Aug 10, 2026
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
69 changes: 69 additions & 0 deletions .agents/skills/address-feedback/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
---
name: address-feedback
description: Fetch a GitHub PR review (Copilot, human, or another agent), verify each finding against the code, fix what is real with regression tests, run the repo gates, and push. Use when the user shares PR review feedback, a pullrequestreview URL, or asks to address review comments.
---

# Address PR review feedback

Turns one review round into one command: fetch → verify → fix → gate → push → report.

## 1. Fetch the feedback

- `.../pull/<n>#pullrequestreview-<id>` URL →
`gh api repos/{owner}/{repo}/pulls/<n>/reviews/<id>` for the body and
`gh api repos/{owner}/{repo}/pulls/<n>/reviews/<id>/comments --paginate` for the
inline comments (always paginate — large reviews span pages).
- Bare PR number → `gh pr view <n> --json reviews,commits` for the review summaries,
plus `gh api repos/{owner}/{repo}/pulls/<n>/comments --paginate` for the inline
comments (`gh pr view` does not return them); keep the ones whose
`pull_request_review_id` belongs to a review submitted since the last push.
- Pasted findings text → use as-is.
- Make sure the PR branch is checked out and current (`gh pr checkout <n>` — never mix
with uncommitted local work; stop and say so if the tree is dirty with unrelated
changes).

## 2. Verify before trusting — triage every finding

Reviews (Copilot especially) contain false positives. For each finding, read the actual
code — whole functions and their callers, not diff hunks — then classify:

- **Agree**: real defect, fix it.
- **Disagree**: false positive or intended behavior. Keep the code evidence; it goes in
the report verbatim.
- **Business decision**: a behavior/product choice (defaults, risk acceptance, who gets
notified, what partners may see). Never guess these — collect them and ask the user,
with a recommendation each (use AskUserQuestion when interactive).

## 3. Fix agreed findings

- Surgical changes only; match surrounding style; no drive-by refactors.
- Per repo rules: every bug that slipped past existing tests gets a regression test that
fails without the fix, in the same commit.
- If the fix changes behavior documented in `docs/security-spec`, sync the owning spec
file in the same change (grep `docs/security-spec/README.md` for the owner).

## 4. Gates before pushing

Trust guard: gates execute branch-local code. Only run them when the PR head lives in
`pendulum-chain/vortex` itself and the author is a known collaborator or team agent;
for fork or external-author PRs, stop after triage and report instead of executing.

Run what the change touches:

- `bun lint:fix` (Biome — except `packages/sdk`, which uses `bun lint` / ESLint inside
the package).
- `bun typecheck`.
- Affected package/app test suites (commands in each subdirectory's CLAUDE.md).
- `bun run build:shared` when `packages/shared` changed, then re-run dependent suites.
- `bun run wire-contract:check` when shared endpoint types or the SDK surface changed;
if the change is intentional, `bun run wire-contract:update` and commit the snapshot
diff with an explicit note on backward compatibility.

## 5. Push and report

- Commit in logical groups using Conventional Commits (`<type>(<scope>): <summary>`).
- Push to the PR branch; watch CI in a background task and fix failures it surfaces.
- Final message: a disposition table — every finding → **Fixed** (commit), **Disagreed**
(evidence), or **Needs your decision** (options + recommendation). Nothing silently
dropped.
- Reply on the PR threads only if the user asks.
52 changes: 52 additions & 0 deletions .agents/skills/babysit-pr/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
---
name: babysit-pr
description: Watch an open PR and keep it moving without manual ferrying — react to new reviews (Copilot, human, agent) and CI failures, push mechanical fixes, and surface business decisions. Use after opening a PR, e.g. "babysit PR 1234" or "watch this PR until it's mergeable".
---

# Babysit a PR

Long-running watch loop for one PR. Autonomous for mechanical work; it never merges the
PR and never resolves business decisions on its own.

## Setup

- Resolve the PR: argument, or the current branch's PR via `gh pr view`.
- Trust guard: this loop runs branch-local code (gates, fixes). Only babysit PRs whose
head lives in `pendulum-chain/vortex` itself with a known collaborator or team agent
as author; for fork or external-author PRs, watch and report only — never execute
branch code.
- Make sure the PR branch is checked out and the tree is clean; stop and report if there
is unrelated uncommitted work.
- Record a baseline to diff against on every wake-up (persist it in a scratch state
file): head SHA, review ids, issue-comment ids, and CI runs from
`gh pr view <n> --json headRefOid,reviews,comments,statusCheckRollup` (its `comments`
field is issue comments only), plus the inline review-comment ids from
`gh api repos/{owner}/{repo}/pulls/<n>/comments --paginate`.
- If no Copilot review exists yet, request one:
`gh api repos/{owner}/{repo}/pulls/<n>/requested_reviewers -f "reviewers[]=copilot-pull-request-reviewer[bot]"`.
If the API rejects the bot reviewer, note it in the report and continue — the user can
request it in the GitHub UI.

## Each iteration

1. Fetch current PR state and diff against the baseline.
2. New CI failure on the current head → read the failing logs
(`gh run view <run-id> --log-failed`), fix, run the repo gates, push.
3. New review or new inline review comments → run the `/address-feedback` flow on them:
verify each finding against the code, fix agreed items with regression tests, run
gates, push. Keep the disagree evidence and any business decisions for the report.
4. New human questions or discussion → draft replies but do not post them unless the
user explicitly enabled posting; include the drafts in the report instead.
5. After pushing fixes prompted by a Copilot review, re-request the Copilot review so
the next round starts without the user ferrying anything.
6. Update the state file.

## Pacing, notifying, stopping

- Pace with the harness loop mechanism (dynamic `/loop` / scheduled wake-ups): check
every 5–15 minutes; after pushing, watch CI to completion in a background task and act
on the result instead of waiting for the next tick.
- Actively notify the user (not just a log line) when: a business decision is pending, a
reviewer pushes back on a disagree disposition, or all feedback is addressed and CI is
green (mergeable — the user's call).
- Stop when the PR is merged or closed, or when the user says stop. Never merge.
50 changes: 50 additions & 0 deletions .agents/skills/ship/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
---
name: ship
description: End-to-end Vortex feature pipeline — plan with decision gates, implement with tests, self-review until dry, open the PR, and hand off to babysit-pr. Use for "ship this feature", "one-shot this", or when starting substantial feature work from a problem statement or handoff document.
---

# Ship a feature

Pipeline with exactly two human gates: plan approval and merge. Everything in between
runs autonomously.

## Phase 0 — Understand and plan (human gate 1)

- Ingest the problem statement, handoff doc, linked PRs/proposals/ADRs.
- Fan out parallel read-only mapping subagents over the affected subsystems (quote
pipeline, phases/blocks, providers, dashboard, SDK — whatever the change touches).
- Draft the implementation plan: approach and alternatives considered, files to touch,
DB/migration impact (including what is already deployed on staging/prod),
`docs/security-spec` impact, wire-contract impact (is a partner-facing change
intended?), and the test plan (which suites, which new tests).
- Collect every open product/behavior decision — defaults, who is notified, what
partners may see, risk acceptances — and ask the user concretely with a
recommendation per question (AskUserQuestion). Never resolve these silently.
- Present the plan and wait for approval before writing any code.

## Phase 1 — Implement

- Work in a fresh worktree branched off the latest `origin/staging`.
- Implement in logical Conventional Commits; ship tests alongside per the repo rules
(features get tests; bug fixes get regression tests that fail without the fix).
- Gates before every push: `bun lint:fix` (ESLint inside `packages/sdk`),
`bun typecheck`, affected test suites, `bun run build:shared` when shared changed,
`bun run wire-contract:check` (update + compatibility note only when the surface
change is intentional), security-spec sync when documented behavior changed.

## Phase 2 — Self-review until dry

- Run `/vortex-review` on the branch.
- Fix the confirmed findings here (this session has implementer context), rerun the
gates, then rerun `/vortex-review`. Repeat until a run reports no new confirmed
findings.
- Findings deliberately not addressed go into the PR description with the reasoning —
never silently dropped.

## Phase 3 — PR and handoff (human gate 2)

- Push and open the PR against `staging`: human-friendly sentence-case title, and a
description covering what/why, the decisions taken in phase 0, test evidence, and the
wire-contract note when the snapshot changed.
- Request a Copilot review and start `/babysit-pr` for the follow-through.
- Merging is always the user's decision.
84 changes: 84 additions & 0 deletions .agents/skills/vortex-review/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
---
name: vortex-review
description: Deep multi-lens review of a Vortex PR or branch. Runs parallel Vortex-specific finder lenses, loops until no new findings, adversarially verifies every finding, and reports severity-ranked results. Use when asked for an in-depth code review, a pre-merge confidence check, or to review a PR/branch/diff.
---

# Vortex deep review

Review-only skill: it produces a findings report and NEVER modifies code. Fixes happen in
the implementing session or via `/address-feedback`.

## 1. Resolve scope

- Argument is a PR number/URL → `gh pr view` for title/description/discussion, `gh pr diff`
for the diff. If the branch isn't checked out locally, check it out in a worktree.
- No argument → diff the current branch against `$(git merge-base HEAD origin/staging)`.
- Build a change inventory: files by workspace, plus flags that route lens emphasis:
migrations touched, `packages/shared` touched, SDK public surface touched,
`docs/security-spec` relevant paths touched, frontend machines/widget touched.
- Trust guard: before running ANY branch-local command (installs, builds, tests,
`wire-contract:check`), confirm the PR head lives in `pendulum-chain/vortex` itself
and the author is a known collaborator or team agent. For fork or external-author
PRs, review by inspection only — read the diff and files, execute nothing from the
branch — and say so in the report.
- Run `bun run wire-contract:check` (after `bun run build:shared` if shared changed).
A stale snapshot on the branch = automatic P1 finding.
- Read the PR description and any linked proposal/ADR: findings include "the change
doesn't achieve its stated intent", not just "the code is wrong".

## 2. Round 1 — finder fleet

Spawn parallel read-only subagents, one per lens (use the Workflow tool if available,
otherwise parallel Agent tasks). Every finder gets: the diff, the change inventory, its
lens brief below, and these standing rules:

- Verify every claim against the actual code — read whole functions/files, never judge
from diff hunks alone. Check whether a suspected issue is already guarded elsewhere.
- Report findings as: severity (P0 blocker / P1 must-fix / P2 should-fix / P3 nit),
`file:line`, one-sentence claim, concrete failure scenario (inputs/state → wrong
outcome), suggested fix, suggested regression test.
- Also report what you checked and found clean.

Lens briefs (these encode the classes that historically slipped through review):

| Lens | Hunt for |
|---|---|
| correctness | Logic errors, wrong conditionals, off-by-one, unhandled branches, race conditions, dead code introduced by the change |
| financial-integrity | Fee math and rounding (Big.js modes), raw (18-dp) vs decimal confusion, subsidy caps, net-rate promise, the same amount derived differently at quote vs settlement vs distribution time |
| phase-recovery | Phase handlers/blocks: idempotency under retry and crash-between-steps; preconditions that can never pass after partial success (e.g. balance checks for funds that already moved); presigned-tx identity must include nonce (phase+network+signer alone collides); retries vs lock expiry; `unknown`-status operations conflated with "not started" |
| silent-failures | Swallowed errors, catch-and-continue, fallbacks that mask wrong data, logs asserting success on unverified paths, error branches that can never fire |
| partner-surface | Anything a live integrator depends on: shared endpoint types, SDK public API and `parseAPIError` message matching vs actual backend error strings, webhook payloads/signing, auth semantics, `docs/api/openapi/vortex.openapi.json` sync, wire-contract snapshot diff review |
| db-migrations | Migrations vs the already-deployed staging/prod schema (edits to already-run migrations never re-run; backfills must handle existing rows); irreversible steps without a runbook; enum exhaustiveness (`FiatToken` has 6 values: EURC, ARS, BRL, USD, MXN, COP — check every `Record<FiatToken, X>`; `SubsidyToken`); Sequelize model ↔ schema drift |
| consistency | Corridor/capability matrix agreement across widget (frontend), API, dashboard, SDK (`tokenAvailability`, `mapFiatToDestination`, `ARRIVAL_TEXT_BY_TOKEN`); i18n in both en and pt-BR; `docs/security-spec` staleness per the CLAUDE.md sync rule |
| test-adequacy | Would the new tests fail without the fix; edge cases vs happy path only; `mock.module` leak rules (snapshot values before mocking, restore in `afterAll`); no production data/PII in fixtures; coverage gates still passing |

For small diffs (< ~150 changed lines) merge to 4 finders: correctness+silent-failures,
financial+phase-recovery, partner-surface+db-migrations, consistency+test-adequacy.

## 3. Loop until dry

- Deduplicate new candidates against everything already seen (file + line + claim), not
only against confirmed findings — otherwise refuted findings resurface forever.
- After any round that produces new candidates, run another fleet round where finders get
the list of everything found so far and the brief "hunt for what these reviewers
missed — different files, different failure classes".
- Stop after two consecutive rounds with zero new candidates (typically 2–3 rounds).

## 4. Adversarial verification

Every candidate goes to a verifier subagent prompted to REFUTE it with code evidence: is
the path reachable, is the behavior actually wrong, is it guarded elsewhere, does the
failure scenario hold? P0/P1 candidates get two independent verifiers; the finding
survives only if the refutation fails. Refuted candidates go to a one-line appendix so
the same false positive isn't re-litigated next run.

## 5. Report

Deliver in the final message (and post via `gh pr review --comment` only if asked):

1. One-paragraph verdict: mergeable or not, and the dominant risk.
2. Findings ranked by severity: `file:line`, claim, failure scenario, fix, regression
test to add.
3. "Verified clean" — per lens, what was checked and held up. Absence of findings must
be evidence of checking, not of not looking.
4. Appendix: refuted candidates (one line each).
1 change: 1 addition & 0 deletions .claude/skills/address-feedback
1 change: 1 addition & 0 deletions .claude/skills/babysit-pr
1 change: 1 addition & 0 deletions .claude/skills/ship
1 change: 1 addition & 0 deletions .claude/skills/vortex-review
5 changes: 5 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ jobs:
- name: ✏️ Typecheck
run: bun run typecheck

- name: 🔒 Wire-contract gate
run: |
cd scripts/wire-contract && bun test && cd ../..
bun run wire-contract:check

test:
name: Running tests
runs-on: ubuntu-latest
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/contracts.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ jobs:
contracts:
name: External API contracts (live)
runs-on: ubuntu-latest
concurrency:
group: external-api-contracts-avenia-sandbox
cancel-in-progress: false
env:
CI: true
RUN_LIVE_TESTS: "1"
Expand Down Expand Up @@ -50,6 +53,7 @@ jobs:
BRLA_API_KEY: ${{ secrets.CONTRACT_BRLA_API_KEY }}
BRLA_PRIVATE_KEY: ${{ secrets.CONTRACT_BRLA_PRIVATE_KEY }}
AVENIA_CONTRACT_SUBACCOUNT_ID: ${{ secrets.CONTRACT_AVENIA_SUBACCOUNT_ID }}
AVENIA_CONTRACT_WEBHOOK_URL: ${{ secrets.CONTRACT_AVENIA_WEBHOOK_URL }}
COINGECKO_API_KEY: ${{ secrets.COINGECKO_API_KEY }}
run: bun test src/tests/contracts/

Expand Down
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,10 @@ storybook-static


CLAUDE.local.md
# Ignore everything under .claude except the team-shared settings.json
# Ignore everything under .claude except the team-shared settings.json and skills
.claude/*
!.claude/settings.json
!.claude/skills/
/.roo/*

# hardhat generated files in workspace contract projects
Expand Down
7 changes: 7 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Repository agent instructions

- Read and follow the root `CLAUDE.md` before doing any work in this repository.
- When work touches an app or package, also read and follow the closest scoped `CLAUDE.md`.
- Commit messages use Conventional Commits: `<type>(<scope>): <summary>`.
- Pull request titles use plain, human-friendly sentence case. Never prefix a PR title with `<type>(<scope>):`.
- Before creating or renaming a pull request, reread the `Commit Messages & PR Titles` section in `CLAUDE.md`.
6 changes: 5 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,14 @@ update the existing canonical document when one owns the topic.
document.
- Keep local `README.md` files only when they explain a non-obvious subsystem contract.
- Repair indexes and relative links in the same change as a move or deletion.
- Agent skills live in `.agents/skills/<name>/SKILL.md` so every coding agent can use
them; `.claude/skills/` holds only symlinks to those directories (Claude Code follows
them for discovery). When adding a skill, create the directory there and add the
matching symlink.

## Commit Messages & PR Titles

Every commit message and PR title follows [Conventional Commits](https://www.conventionalcommits.org/):
Every commit message follows [Conventional Commits](https://www.conventionalcommits.org/):

```
<type>(<scope>): <summary>
Expand Down
Loading
Loading