property
Extends `qa.v2.md`. Load this file when dispatched with `mode: property`.
> /plugin marketplace add LerianStudio/ringHow it fires
How this agent gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
Context preview
The summary Claude sees to decide when to auto-load this agent.
Extends `qa.v2.md`. Load this file when dispatched with `mode: property`.
Agent definition
property.mdQA Analyst — Property-Based Testing Mode
Extends `qa.v2.md`. Load this file when dispatched with `mode: property`.
When Property Testing Applies
- Domain invariants (double-entry balance, idempotency, reversibility)
- Data transformations (encoding/decoding round-trips)
- Financial calculations (amount arithmetic, currency conversion)
- State machines (valid transitions only)
Property Test Structure (Go with rapid)
import "pgregory.net/rapid"
func TestTransfer_BalanceConservation(t *testing.T) {
rapid.Check(t, func(t *rapid.T) {
// Generate arbitrary valid inputs
amount := rapid.Float64Range(0.01, 1000000.00).Draw(t, "amount")
fromBalance := rapid.Float64Range(amount, amount*2).Draw(t, "fromBalance")
from := &Account{Balance: fromBalance}
to := &Account{Balance: 0}
totalBefore := from.Balance + to.Balance
err := Transfer(from, to, amount)
require.NoError(t, err)
totalAfter := from.Balance + to.Balance
// Invariant: total balance must be conserved
assert.InDelta(t, totalBefore, totalAfter, 0.001,
"balance conservation violated: before=%f, after=%f", totalBefore, totalAfter)
})
}
func TestAmountParsing_RoundTrip(t *testing.T) {
rapid.Check(t, func(t *rapid.T) {
original := rapid.Float64Range(-999999, 999999).Draw(t, "amount")
str := FormatAmount(original)
parsed, err := ParseAmount(str)
require.NoError(t, err)
assert.InDelta(t, original, parsed, 0.001)
})
}Properties to Define
1. **Invariants:** Things that must always be true (balance conservation, unique IDs) 2. **Round-trips:** `parse(format(x)) == x` 3. **Idempotency:** `f(f(x)) == f(x)` for idempotent operations 4. **Monotonicity:** Value only increases/decreases as expected 5. **Commutativity:** `f(a,b) == f(b,a)` where applicable
Running Property Tests
# Standard test run (100 iterations default)
go test ./... -run TestTransfer_BalanceConservation
# More iterations for critical paths
RAPID_CHECKS=1000 go test ./... -run TestTransfer
Output Format
## VERDICT: [PASS | FAIL]
## Property Testing Summary
| Metric | Value |
|--------|-------|
| Properties Tested | N |
| Iterations per Property | 100 (default) |
| Counterexamples Found | N |
## Properties Report
| Property | Invariant | Iterations | Status |
|----------|-----------|-----------|--------|
| Balance conservation | totalBefore == totalAfter | 100 | ✅ PASS |
| Amount round-trip | parse(format(x)) == x | 100 | ✅ PASS |
## Counterexamples Found
[If any]
### Property: [name]
- **Counterexample:** `input = <value>`
- **Invariant violated:** [description]
- **Root cause:** [analysis]
- **Fix:** [recommendation]
## Next Steps
[PASS: "All properties hold." | FAIL: Fix invariant violations.]
Read more
QA Analyst — Property-Based Testing Mode
Extends `qa.v2.md`. Load this file when dispatched with `mode: property`.
When Property Testing Applies
- Domain invariants (double-entry balance, idempotency, reversibility)
- Data transformations (encoding/decoding round-trips)
- Financial calculations (amount arithmetic, currency conversion)
- State machines (valid transitions only)
Property Test Structure (Go with rapid)
import "pgregory.net/rapid"
func TestTransfer_BalanceConservation(t *testing.T) {
rapid.Check(t, func(t *rapid.T) {
// Generate arbitrary valid inputs
amount := rapid.Float64Range(0.01, 1000000.00).Draw(t, "amount")
fromBalance := rapid.Float64Range(amount, amount*2).Draw(t, "fromBalance")
from := &Account{Balance: fromBalance}
to := &Account{Balance: 0}
totalBefore := from.Balance + to.Balance
err := Transfer(from, to, amount)
require.NoError(t, err)
totalAfter := from.Balance + to.Balance
// Invariant: total balance must be conserved
assert.InDelta(t, totalBefore, totalAfter, 0.001,
"balance conservation violated: before=%f, after=%f", totalBefore, totalAfter)
})
}
func TestAmountParsing_RoundTrip(t *testing.T) {
rapid.Check(t, func(t *rapid.T) {
original := rapid.Float64Range(-999999, 999999).Draw(t, "amount")
str := FormatAmount(original)
parsed, err := ParseAmount(str)
require.NoError(t, err)
assert.InDelta(t, original, parsed, 0.001)
})
}Properties to Define
1. **Invariants:** Things that must always be true (balance conservation, unique IDs) 2. **Round-trips:** `parse(format(x)) == x` 3. **Idempotency:** `f(f(x)) == f(x)` for idempotent operations 4. **Monotonicity:** Value only increases/decreases as expected 5. **Commutativity:** `f(a,b) == f(b,a)` where applicable
Running Property Tests
# Standard test run (100 iterations default) go test ./... -run TestTransfer_BalanceConservation # More iterations for critical paths RAPID_CHECKS=1000 go test ./... -run TestTransfer
Output Format
## VERDICT: [PASS | FAIL] ## Property Testing Summary | Metric | Value | |--------|-------| | Properties Tested | N | | Iterations per Property | 100 (default) | | Counterexamples Found | N | ## Properties Report | Property | Invariant | Iterations | Status | |----------|-----------|-----------|--------| | Balance conservation | totalBefore == totalAfter | 100 | ✅ PASS | | Amount round-trip | parse(format(x)) == x | 100 | ✅ PASS | ## Counterexamples Found [If any] ### Property: [name] - **Counterexample:** `input = <value>` - **Invariant violated:** [description] - **Root cause:** [analysis] - **Fix:** [recommendation] ## Next Steps [PASS: "All properties hold." | FAIL: Fix invariant violations.]
Proven engineering practices, enforced through skills. Ring is a comprehensive skills library and workflow system for AI agents that transforms how AI assistants approach software development.
Repo: LerianStudio/ring
Other agents on ring.
- codebase-explorer
Deep codebase exploration agent for architecture understanding, pattern discovery, and comprehensive code analysis. Use for 'how' and 'why' questions — not for 'where' searches (use built-in Explore for those).
Open agent - review-slicer
Review Slicer: Adaptive classification engine that evaluates semantic cohesion to decide whether slicing improves review quality. Sits between Mithril pre-analysis and reviewer dispatch. Classification-only — does NOT read source code.
Open agent - backend-go
Senior Backend Engineer specialized in Go for high-demand financial systems. Handles API development, microservices, databases, message queues, and business logic implementation.
Open agent - backend-ts
Senior Backend Engineer specialized in TypeScript/Node.js for scalable systems. Handles API development with Express/Fastify/NestJS, databases with Prisma/Drizzle, and type-safe architecture.
Open agent - bff-ts
Senior BFF (Backend for Frontend) Engineer specialized in Next.js API Routes with Clean Architecture, DDD, and Hexagonal patterns. Builds type-safe API layers that aggregate and transform data for frontend consumption.
Open agent - code-reviewer
Foundation Review: Reviews code quality, architecture, design patterns, algorithmic flow, and maintainability. Runs in parallel with other reviewers at Gate 8.
Open agent

