Skip to content
Development
Skill

/nw-tdd-cross-language

Port the state-delta + property-based testing paradigm to languages other than Python. DIY recipes per language; canonical Python ref shipped in nwave_ai.state_delta.

From plugin
nwave
628151 skills34 agents27 commands

Claude Code

$ npx -y skills add nWave-ai/nWave --skill nw-tdd-cross-language --agent claude-code

SKILL.md

nw-tdd-cross-language.SKILL.md
name: nw-tdd-cross-language
description: Port the state-delta + property-based testing paradigm to languages other than Python. DIY recipes per language; canonical Python ref shipped in nwave_ai.state_delta.
user-invocable: false
disable-model-invocation: true

Cross-Language State-Delta Porting Guide

This optional implementation guide is not a requirement to port an nWave API. Native discovery and applicability live in `nw-test-design-mandates`; its layered-mechanics module owns observation laws. Use incumbent native assertions, generators, shrinking/replay and helpers first. Matching `nw-pbt-*` guidance loads on need; unlisted languages use their real native tooling, not an `EVIDENCE_GAP` merely because no adapter is shipped. Never borrow Python as a substitute. The recipes below illustrate one optional helper implementation.

Unlisted languages (C, C++, OCaml, etc.) use their own native test, generator, shrinker and replay libraries; no Python-derived shim is imposed.

---

Canonical Python reference

**Illustrative Python API contract** (semantics reference only; not a required API, file path or predicate count; see `nwave_ai.state_delta.matcher`):

def assert_state_delta(
    before: Mapping[str, Any],
    after: Mapping[str, Any],
    universe: set[str],
    expected: Mapping[str, Predicate],
    *,
    strict: bool = False,
) -> None: ...

Predicate = Callable[[Any, Any], bool]

# Illustrative predicate factories (not a required set or count):
def prepended_with(prefix: str, sep: str = ":") -> Predicate: ...
def appended_with(suffix: str, sep: str = ":") -> Predicate: ...
def unchanged() -> Predicate: ...
def set_to(value: Any) -> Predicate: ...
def containing(substring: str) -> Predicate: ...
def normalized_to(normalizer: Callable[[Any], Any]) -> Predicate: ...
def idempotent_after(prefix: str, sep: str = ":") -> Predicate: ...
def legacy_healed(detector: Callable[[Any], bool], healed_check: Callable[[Any], bool]) -> Predicate: ...

**Semantics**:

  • For each key in `universe`:
  • If in `expected`: predicate must return True
  • If NOT in `expected`: implicit-unchanged (`before[k] == after[k]`)
  • `strict=True`: keys in `(before|after) - universe` raise `kind=strict_universe_mismatch`
  • Multi-violation: ALL violations collected, ONE AssertionError raised

---

Porting recipe (conditional, language-agnostic)

Only when an existing native assertion/helper cannot express a needed public-state preservation observation, consider a small project-idiomatic helper. Translate the semantics needed by actual consumers, not a mandatory eight-predicate API or fixed path. Do not create a shim or additional allocations merely to match this illustrative Python reference.

Step 1 — Translate the semantics, only if a helper is needed

Adapt the function signatures using language-idiomatic types:

  • Universe = set/list of strings (`Set<String>`, `string[]`, `&[String]`, etc.)
  • Expected = map of string → predicate (`Map<String, Predicate>`, `{[key: string]: Predicate}`, `HashMap<String, Box<dyn Fn>>`)
  • Predicate = callable taking `(old, new) → bool`

Step 2 — Multi-violation collector (illustrative)

function assert_state_delta(before, after, universe, expected, strict=false):
    violations = []
    for key in universe:
        if key in expected:
            predicate = expected[key]
            if not predicate(before[key], after[key]):
                violations.append(predicate_failed_violation(key, before[key], after[key]))
        else:
            if before[key] != after[key]:
                violations.append(undeclared_change_violation(key, before[key], after[key]))
    if strict:
        for key in (before.keys ∪ after.keys) - universe:
            violations.append(strict_universe_mismatch_violation(key, before.get(key), after.get(key)))
    if violations:
        raise AssertionError(format_multiline_message(violations))

Step 3 — Predicates (only those consumers need)

Include only the predicates actual tests need; the Python eight are illustrative, not a required count. If added, each closes over its parameters using the language's idiom (illustrative: TypeScript arrow functions, Rust `move` closures, F# partial application, Java lambdas, Go returned funcs).

Step 4 — Compose with the native PBT library (if any)

If the project already has a generator/shrinker/replay library, it generates inputs and the native assertion or helper validates post-action state. Illustrative sketch:

property "installer preserves user PATH":
    forall(path: gen_realistic_path):
        before = capture_state()
        installer.install(path)
        after = capture_state()
        assert_state_delta(before, after,
                          universe={"PATH", "permissions", "hooks"},
                          expected={"PATH": prepended_with(app_bin)},
                          strict=true)

---

Illustrative mini-examples per language (not required APIs, paths or LOC)

TypeScript / fast-check

import { fc } from 'fast-check';
import { assertStateDelta, prependedWith } from './state-delta';  // hypothetical helper

fc.assert(
  fc.property(pathStrategy(), (userPath) => {
    const before = captureState();
    installShims(userPath);
    const after = captureState();
    assertStateDelta(before, after, {
      universe: ['PATH', 'permissions', 'hooks'],
      expected: { PATH: prependedWith('/app/bin') },
      strict: true,
    });
  })
);

Rust / proptest

use proptest::prelude::*;
use crate::state_delta::{assert_state_delta, prepended_with};  // hypothetical helper

proptest! {
    #[test]
    fn installer_preserves_user_path(user_path in path_strategy()) {
        let before = capture_state();
        install_shims(&user_path);
        let after = capture_state();
        assert_state_delta(
            &before, &after,
            &["PATH", "permissions", "hooks"],
            &[("PATH
Read more
@nwave-ai
Ships withnwave

AI agents that guide you from idea to working code, with human judgment at every gate. nWave runs inside Claude Code. It breaks feature delivery into seven waves (discover, diverge, discuss, design, devops, distill, deliver).

628151 skills34 agents
Get the whole plugin

Stars on GitHub

Momentum

stars in total
628
Star history of nWave-ai/nWave on GitHub, a chart by star-history.com

Other skills on nwave.

nw-ad-critique-dimensions

nw-ad-critique-dimensi…

Review dimensions for acceptance test quality - happy path bias, GWT compliance, business language purity, coverage completeness,…

@nwave-ai@nwave-aiInstall Skill
nw-agent-testing

nw-agent-testing

5-layer testing approach for agent validation including adversarial testing, security validation, and prompt injection resistance

@nwave-ai@nwave-aiInstall Skill

More skills from other plugins.

brainstorming
Auto-invoked

brainstorming

You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…

@obra@obraInstall Skill
ask-matt

ask-matt

Ask which skill or flow fits your situation. A router over the skills in this repo.

skills11d309k
@mattpocock@mattpocockInstall Skill
accessibility
Auto-invoked

accessibility

Design, implement, and audit accessible UI to WCAG 2.2 Level AA across Web, iOS, and Android — semantic ARIA roles and labels,…

ecc12d293k
@affaan-m@affaan-mInstall Skill
compiler-commit

compiler-commit

Use when you want to verify compiler changes and commit with the correct convention. Runs tests, lint, and format, then commits…

react2d252k
@facebook@facebookInstall Skill

Questions about nw-tdd-cross-language.

Which coding agents can use nw-tdd-cross-language?
nw-tdd-cross-language installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.