All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
- Risk group scoped failures now produce correct exclusions;
compute_exclusionspasses flattened attribute dicts to policy matching instead of rawRiskGroupobjects
- Relicensed from BSD-3-Clause to MIT
- Cached failure-rule candidate pools in
FailureManager, avoiding repeated condition matching across Monte Carlo iterations - Cached risk group membership index for O(1) node/link exclusion lookup on risk group failure
- Relicensed from GPL-3.0-or-later to BSD-3-Clause
- Relicensed from AGPL-3.0-or-later to GPL-3.0-or-later
- Python 3.14 support, including free-threaded (no-GIL) builds in CI
- Single shared RNG per
apply_failurescall, fixing correlated-seed bug across rules - Bracket-exhaustion edge case in MSD binary search when all probed alphas are feasible
seeds_per_alphaMSD parameter (placement is deterministic)SeedManager.create_random_state()andseed_global_random()(unused)
- Link path filter now uses deterministic
{source}|{target}instead of full link ID
- Version management simplified
- DSL skill documentation aligned with implementation; removed unused
demand_placedschema field
- BREAKING: DSL syntax refinement with renamed fields and restructured expansion blocks; see updated DSL reference
- Module reorganization:
ngraph.execsplit intongraph.analysis(runtime analysis) andngraph.model(data structures); public API unchanged via re-exports - Expanded public API:
TrafficDemand,FlowPolicyPreset,Scenario,NetworkExplorer, and placement functions now exported from top-level modules - Placement analysis: Extracted SPF caching and demand placement logic into
ngraph.analysis.placementmodule withplace_demands()andPlacementResult
ngraph.model.demandsubpackage:TrafficDemandand builder functionsngraph.model.flowsubpackage:FlowPolicyPresetand policy configurationngraph.typesexports:Mode,FlowPlacement,EdgeSelect,EdgeRef,MaxFlowResult
- Dynamic risk group creation:
membershiprules auto-assign entities by attribute matching;generateblocks create groups from unique attribute values - Risk group validation: Undefined references and circular hierarchies detected at load time
- Dot-notation in conditions:
attrfield supports nested paths (e.g.,hardware.vendor)
match.logicdefaults now context-aware:"or"for adjacency/demands,"and"for membership rules
- BREAKING: Monte Carlo results restructured:
baselinereturned separately;resultscontains deduplicated failure patterns withoccurrence_count - BREAKING:
baselineparameter removed from Monte Carlo APIs; baseline always runs implicitly
FlowIterationResult.occurrence_count: how many iterations produced this failure patternFlowIterationResult.failure_trace: mode/rule selection details whenstore_failure_patterns=True
- BREAKING:
TrafficDemand.source_path/sink_pathrenamed tosource/sink; now accept string patterns or selector dicts withpath,group_by, andmatchfields - BREAKING: Removed
attr:<name>magic string syntax; use{"group_by": "<name>"}dict selectors instead - BREAKING: Removed
ngraph.utils.nodesmodule; usengraph.dsl.selectorsfor node selection - Unified selector system:
ngraph.dsl.selectorsprovidesnormalize_selector()andselect_nodes()for consistent node selection across demands, workflows, adjacency, and overrides - Variable expansion in demands:
TrafficDemandsupportsexpand_varswith$var/${var}syntax andexpansion_mode(cartesian/zip) - Match conditions: Selector
matchfield supports 12 operators:==,!=,<,<=,>,>=,contains,not_contains,in,not_in,any_value,no_value - Context-aware defaults:
active_onlydefaults toTruefor demands/workflows,Falsefor adjacency/overrides
ngraph.dsl.selectorsmodule:NodeSelector,MatchSpec,Conditionschema classesngraph.dsl.expansionmodule:ExpansionSpec,expand_templates(),substitute_vars(),expand_name_patterns(),expand_risk_group_refs()- Bracket expansion in risk groups:
[1-3]and[a,b,c]patterns now expand in risk group definitions (including children) and membership arrays on nodes, links, and groups TrafficDemand.group_modefield for node group handling (flatten,per_group,group_pairwise).claude/skills/netgraph-dsl/: Claude skill with DSL syntax reference and examples
- SPF caching in demand placement:
demand_placement_analysis()caches SPF results by (source, policy_preset) for ECMP, WCMP, and TE_WCMP_UNLIM policies; TE policies recompute when capacity constraints require alternate paths - MSD AnalysisContext caching:
MaximumSupportedDemandbuildsAnalysisContextonce and reuses it across all binary search probes
- TrafficDemand ID preservation: Fixed context caching with
mode: combineby ensuringTrafficDemand.idis preserved through serialization; pseudo node names now remain consistent across context build and analysis
- Cache key generation: Use
id()instead ofstr()for non-hashable kwargs in_create_cache_key()to avoid expensive__repr__traversals on large objects
- NetworkX interop: New
ngraph.lib.nxmodule withfrom_networkx()andto_networkx()for converting between NetworkX graphs and netgraph_core.StrictMultiDiGraph - Mapping classes:
NodeMapandEdgeMapfor bidirectional node/edge ID lookups after conversion
- BREAKING: Minimum Python version raised to 3.11
- Dependencies: Updated netgraph-core to >=0.3.0
- AnalysisContext API:
analyze()now returns anAnalysisContextfor max-flow, shortest paths, and sensitivity analysis with reusable state.
- Performance runner & workflows: Reuse bound
AnalysisContextto avoid rebuilding Core graphs across repeated analyses. - Docs & examples: Updated guides and reference docs to describe the new analysis API and bound-context workflow.
- Failure handling: More consistent tracking of disabled nodes and links during analysis.