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.
npx skills add https://github.com/nWave-ai/nWave --skill nw-tdd-cross-language
The state-delta + property-based testing paradigm (see nw-tdd-methodology::Paradigm Mandate) is shipped natively in Python via nwave_ai.state_delta. This skill documents how to apply the same paradigm in other languages with idiomatic adaptations.
Open source positioning (nwave-ai master): Python canonical + DIY porting guide. Users in other languages port the pattern using their language's PBT library + a small state-delta shim (~70-150 LOC).
Enterprise positioning (nwave-pro bundle, deferred): pre-built language packages with tested implementations, kept consistent across versions.
| Language | Test framework | PBT library | State-delta port size | Idiomatic notes |
|---|---|---|---|---|
| Python | pytest | Hypothesis | shipped (nwave_ai.state_delta, ~250 LOC) | Reference implementation. Closure-over-parameters predicates, frozen dataclass Violation. |
| TypeScript / JS | vitest, jest, mocha | fast-check | ~80 LOC | Generics over Old, New. Predicate = (old: O, new: N) => boolean. Use expect.fail() for AssertionError equivalent. |
| Java | JUnit 5 | jqwik | ~120 LOC | Verbose generics (Predicate<O, N>). Builder pattern for assertStateDelta(...) fluent API. Use AssertionError. |
| Kotlin | kotest (built-in PBT) | native | ~80 LOC | DSL idiomatic — assertStateDelta { universe(...) ; expected(...) }. Lambda predicates fit naturally. |
| F# / .NET | xUnit, NUnit | FsCheck | ~70 LOC | Functional fit naturale. Discriminated unions for Violation, partial application for predicate factories. |
| Rust | cargo test | proptest | ~100 LOC | Fn traits for predicates. struct Violation with derive(Clone, Debug). Returns Result<(), AssertionError>. |
| Go | testing | gopter, quick | ~150 LOC | More verbose due to lack of closures over generics. Predicate = function accepting interface{}. Use t.Errorf for assertion. |
| OCaml | alcotest | qcheck | ~70 LOC | Functional fit naturale. Variant types for Violation, partial application natural. |
| Scala | ScalaTest | ScalaCheck | ~80 LOC | Pattern matching for Violation, implicit conversions for fluent predicate composition. |
API contract (locked at pilot, 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]
# 8 predicate factories:
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:
universe:expected: predicate must return Trueexpected: implicit-unchanged (before[k] == after[k])strict=True: keys in (before|after) - universe raise kind=strict_universe_mismatchFor ANY language, the port is a small shim around the language's PBT library + an assert_state_delta function that captures the multi-violation collection semantics. Keep it small (~70-150 LOC). Do not over-engineer.
Adapt the function signatures using language-idiomatic types:
Set<String>, string[], &[String], etc.)Map<String, Predicate>, {[key: string]: Predicate}, HashMap<String, Box<dyn Fn>>)(old, new) → boolfunction 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))
Each factory closes over its parameters and returns a callable. Use language-idiomatic closure mechanism:
move closures returning impl Fn(...) -> boolFunction/BiPredicatefunc(old, new interface{}) boolCombine with language's PBT library. The PBT library generates inputs; assert_state_delta validates the post-action state.
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(des_bin)},
strict=true)
import { fc } from 'fast-check';
import { assertStateDelta, prependedWith } from './state-delta'; // ~80 LOC shim
fc.assert(
fc.property(pathStrategy(), (userPath) => {
const before = captureState();
installShims(userPath);
const after = captureState();
assertStateDelta(before, after, {
universe: ['PATH', 'permissions', 'hooks'],
expected: { PATH: prependedWith('/des/bin') },
strict: true,
});
})
);
use proptest::prelude::*;
use crate::state_delta::{assert_state_delta, prepended_with}; // ~100 LOC shim
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", prepended_with("/des/bin"))],
true, // strict
).unwrap();
}
}
open FsCheck.Xunit
open StateDelta // ~70 LOC shim
[<Property>]
let ``installer preserves user PATH`` (userPath: PathShape) =
let before = captureState()
installShims userPath
let after = captureState()
assertStateDelta before after
[ "PATH"; "permissions"; "hooks" ]
[ "PATH", prependedWith "/des/bin" ]
StrictMode.Strict
import net.jqwik.api.*;
import org.example.statedelta.StateDelta; // ~120 LOC shim
class InstallerProperties {
@Property
void installerPreservesUserPath(@ForAll("paths") String userPath) {
var before = captureState();
installer.install(userPath);
var after = captureState();
StateDelta.assertStateDelta(
before, after,
Set.of("PATH", "permissions", "hooks"),
Map.of("PATH", StateDelta.prependedWith("/des/bin")),
true // strict
);
}
}
If the SUT (system under test) is a Python service or CLI:
assert_state_delta directly via test fixtureIf the SUT is in your language but you only need state-delta for a few critical surfaces:
assert_state_delta + 2-3 predicates you actually need)The 3-stage cascade in nw-tdd-methodology::Paradigm Mandate applies regardless of language:
Stage applicability is independent of language. Language port is enabling infrastructure; the paradigm itself is universal.
If your organization needs:
These ship as part of the nwave-pro enterprise bundle (deferred — contact the nWave team). Open-source path is sufficient for paradigm validation; enterprise reduces porting effort + adds support.
| Task | Resource |
|---|---|
| Read paradigm mandate | nw-tdd-methodology::Paradigm Mandate |
| Read stage cascade | nw-tdd-methodology::Empirical efficacy framework |
| Python canonical implementation | nwave_ai.state_delta (matcher.py + predicates.py) |
| Python pilot example | tests/state_delta/integration/test_pilot_bug48.py (D-12 Part A + B) |
| Roadmap directive (architects) | nw-roadmap::Test paradigm mandate |
For language-specific PBT library docs, see official:
https://fast-check.dev/https://docs.rs/proptest/https://jqwik.net/https://fscheck.github.io/FsCheck/https://github.com/leanovate/gopterhttps://scalacheck.org/https://github.com/c-cube/qcheckhttps://kotest.io/docs/proptest/property-based-testing.htmlToolkit for interacting with and testing local web applications using Playwright. Supports verifying frontend functionality, debugging UI behavior, capturing browser screenshots, and viewing browser logs.
Use when implementation is complete, all tests pass, and you need to decide how to integrate the work - guides completion of development work by presenting structured options for merge, PR, or cleanup
Use when implementing any feature or bugfix, before writing implementation code
Use when encountering any bug, test failure, or unexpected behavior, before proposing fixes
Use when about to claim work is complete, fixed, or passing, before committing or creating PRs - requires running verification commands and confirming output before making any success claims; evidence before assertions always
Expert guidance for systematic backtesting of trading strategies. Use when developing, testing, stress-testing, or validating quantitative trading strategies. Covers "beating ideas to death" methodology, parameter robustness testing, slippage modeling, bias prevention, and interpreting backtest results. Applicable when user asks about backtesting, strategy validation, robustness testing, avoiding overfitting, or systematic trading development.
Cloud laboratory platform for automated protein testing and validation. Use when designing proteins and needing experimental validation including binding assays, expression testing, thermostability measurements, enzyme activity assays, or protein sequence optimization. Also use for submitting experiments via API, tracking experiment status, downloading results, optimizing protein sequences for better expression using computational tools (NetSolP, SoluProt, SolubleMPNN, ESM), or managing protein design workflows with wet-lab validation.
This skill should be used for time series machine learning tasks including classification, regression, clustering, forecasting, anomaly detection, segmentation, and similarity search. Use when working with temporal data, sequential patterns, or time-indexed observations requiring specialized algorithms beyond standard ML approaches. Particularly suited for univariate and multivariate time series analysis with scikit-learn compatible APIs.
Take nwave-ai/nw-tdd-cross-language from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.