Skip to content
cccskills
FreePublished on GitHub

property-based-testing

fast-check patterns for JS/TS — 6 canonical property categories with worked examples targeting agent-studio utilities (path normalization, safe-json, glob-to-regex, routing logic)

The English summary is being prepared. Showing the original description.

See how to install

Files included (10)

  • SKILL.md5.8 KB
  • commands/property-based-testing.md122 B
  • hooks/post-execute.cjs322 B
  • hooks/pre-execute.cjs439 B
  • references/research-requirements.md478 B
  • rules/property-based-testing.md525 B
  • schemas/input.schema.json660 B
  • schemas/output.schema.json266 B
  • scripts/main.cjs555 B
  • templates/implementation-template.md196 B

SKILL.md (original)

Review the instructions the agent will receive before you install.

Property-Based Testing

fast-check patterns for JavaScript/TypeScript that find edge cases unit tests miss. Includes 6 canonical property categories with worked examples targeting agent-studio's own utilities.

When to Use

  • New utility functions (path normalization, parsers, transformers)
  • Bug fixes where the fix has a general invariant (not just the specific repro case)
  • Security-sensitive string handling (avoid escaping bugs, injection vectors)
  • Any function where "this property should hold for ALL inputs" can be stated

The 6 Canonical Property Categories

1. Inverse Operations (Round-trip)

import fc from 'fast-check';
// If you serialize then deserialize, you get back the original
fc.assert(
  fc.property(fc.anything(), value => {
    expect(deserialize(serialize(value))).toEqual(value);
  })
);

2. Idempotency

// Applying a function twice gives same result as once
fc.assert(
  fc.property(fc.string(), str => {
    expect(normalize(normalize(str))).toEqual(normalize(str));
  })
);

3. Commutativity / Order Independence

// Order of inputs shouldn't matter
fc.assert(
  fc.property(fc.array(fc.integer()), arr => {
    expect(sum(arr)).toEqual(sum([...arr].reverse()));
  })
);

4. Invariants (Properties that must always hold)

// Output always has certain structural properties
fc.assert(
  fc.property(fc.string(), input => {
    const result = parseArgs(input);
    expect(result).toHaveProperty('args');
    expect(Array.isArray(result.args)).toBe(true);
  })
);

5. Oracle Comparison (Simpler reference implementation)

// Compare fast implementation against slow-but-correct reference
fc.assert(
  fc.property(fc.array(fc.integer()), arr => {
    expect(fastSort(arr)).toEqual(referenceSort(arr));
  })
);

6. Metamorphic Relations

// If input changes in a known way, output changes in a predictable way
fc.assert(
  fc.property(fc.array(fc.integer()), arr => {
    const sorted = sort(arr);
    const sortedWithExtra = sort([...arr, Number.MAX_SAFE_INTEGER]);
    expect(sortedWithExtra[sortedWithExtra.length - 1]).toBe(Number.MAX_SAFE_INTEGER);
  })
);

Agent-Studio Specific Examples

Path Normalization (targets SE-01 from sharp-edges)

import fc from 'fast-check';
const { normalizePath } = require('.claude/lib/utils/path-constants.cjs');

// Property: normalized path never contains backslashes
fc.assert(
  fc.property(fc.string(), path => {
    expect(normalizePath(path)).not.toMatch(/\\/);
  })
);

// Property: idempotent
fc.assert(
  fc.property(fc.string(), path => {
    expect(normalizePath(normalizePath(path))).toEqual(normalizePath(path));
  })
);

Safe JSON Parser (targets SE-02 from sharp-edges)

const { safeParseJSON } = require('.claude/lib/utils/safe-json.cjs');

// Property: never throws, always returns { success, data }
fc.assert(
  fc.property(fc.string(), input => {
    const result = safeParseJSON(input, null);
    expect(result).toHaveProperty('success');
    expect(typeof result.success).toBe('boolean');
  })
);

// Property: prototype pollution not possible
fc.assert(
  fc.property(fc.string(), input => {
    const before = Object.prototype.toString;
    safeParseJSON(input, null);
    expect(Object.prototype.toString).toBe(before);
  })
);

Glob-to-Regex (targets SE-05 from sharp-edges)

// Property: patterns with **/dir/** match root-level dir
fc.assert(
  fc.property(fc.constantFrom('foo', 'bar', 'baz'), dir => {
    const pattern = `**/${dir}/**`;
    const regex = globToRegex(pattern);
    expect(`${dir}/file.js`).toMatch(regex); // root-level match
    expect(`a/${dir}/file.js`).toMatch(regex); // nested match
  })
);

Routing Logic

// Property: routing is deterministic (same input -> same agent)
fc.assert(
  fc.property(fc.string(), intent => {
    expect(route(intent)).toEqual(route(intent));
  })
);

// Property: routing never returns null/undefined
fc.assert(
  fc.property(fc.string(), intent => {
    expect(route(intent)).toBeTruthy();
  })
);

Installation

pnpm add -D fast-check

Running Property Tests

# Run all property tests
node --test tests/**/*.property.test.cjs

# Run with verbose output (shows counterexamples on failure)
FAST_CHECK_VERBOSE=true node --test tests/**/*.property.test.cjs

Shrinkage (Automatic Counterexample Minimization)

fast-check automatically shrinks failing inputs to the minimal counterexample. Example:

  • Test fails on: "C:\\Users\\foo\\deep\\nested\\path"
  • fast-check shrinks to: "a\\b" (minimal backslash case)

This makes debugging far faster than traditional fuzzing.

Memory Protocol (MANDATORY)

Before starting: Read .claude/context/memory/learnings.md

After completing:

  • New pattern -> .claude/context/memory/learnings.md
  • Issue found -> .claude/context/memory/issues.md
  • Decision made -> .claude/context/memory/decisions.md

ASSUME INTERRUPTION: If it's not in memory, it didn't happen.

Reviews

No reviews yet. Tell others what you thought.

Comments

No login needed. Share how it worked for you, ask a question, or note where it did not run.

No comments yet. Be the first to write one.

Comments are published right away. Do not include personal information such as email addresses or phone numbers. Up to 2 URLs.

0 / 1,000 characters

This form is protected by reCAPTCHA, and the Google Privacy Policy and Terms of Service apply.

More skills from this repository

Ensure accessibility in UI components including semantic HTML, ARIA attributes, keyboard navigation, and WCAG 2.2 AA compliance.

The English summary is being prepared. Showing the original description.

oimiragieo/agent-studio42Updated Jul 14, 2026

Use when you want to improve response quality through meta-cognitive reasoning. Applies 15+ reasoning methods to reconsider and refine initial outputs.

The English summary is being prepared. Showing the original description.

oimiragieo/agent-studio42Updated Jul 14, 2026

N-round opposing-stance debates for trade-off analysis. Assigns pro/con roles to agents, runs structured debate rounds with quality scoring, and produces a moderator synthesis with confidence-rated recommendation. Generalizable to architecture, technology, security, and design decisions.

The English summary is being prepared. Showing the original description.

oimiragieo/agent-studio42Updated Jul 14, 2026

Force adversarial code review stance that eliminates confirmation bias — reviewer must find issues or re-analyze

The English summary is being prepared. Showing the original description.

oimiragieo/agent-studio42Updated Jul 14, 2026

Creates specialized AI agents on-demand when no existing agent matches a request. Use when the Router cannot find a suitable agent for a task. Enables self-evolution by generating persistent agents.

The English summary is being prepared. Showing the original description.

oimiragieo/agent-studio42Updated Jul 14, 2026

LLM-as-judge evaluation framework with 5-dimension rubric (accuracy, groundedness, coherence, completeness, helpfulness) for scoring AI-generated content quality with weighted composite scores and evidence citations

The English summary is being prepared. Showing the original description.

oimiragieo/agent-studio42Updated Jul 14, 2026

See all skills by oimiragieo

Report a problem with this skill