Releases: ainetus/Co-Study4Grid
Release list
Co-Study4Grid 0.8.0
Co-Study4Grid 0.8.0
A feature-rich release that broadens what an operator can do in a study,
consolidates the UI, adds two new ways to run the tool, and quietly
hardens the codebase underneath. Paired with expert_op4grid_recommender
0.2.4 (required for the GST / superposition paths); from this release on,
CI tracks the latest published recommender rather than a pinned version.
Upgrades from 0.7.5. Sessions saved on 0.7.x reload unchanged
(model/compute_overflow_graph/ new action-type fields fall back
to their legacy defaults).
🧰 A bigger remedial-action vocabulary
- Redispatching actions — raise/lower a dispatchable generator with an
editable signed MW delta (±10 MW default), end-to-end through scoring,
the ActionCard editor, simulation, save/reload and the interaction log. - GST estimation for injection pairs — the Explore-Pairs estimate now
covers pairs involving load shedding / curtailment / redispatch (not just
topology), via the recommender's Generalized Superposition Theorem. The
"cannot be combined for estimation" caveats are gone. - Restrict the recommender to chosen action types — a new Settings →
Recommender control scopes proposals to a subset of families (fixing the
long-standing "Min = 0 doesn't exclude a family" confusion).
✎ Interactive SLD topology editing
Build a remedial action by clicking breakers on a Single Line Diagram
(mirrors the library's manoeuvre_ihm): a live target-topology preview
(no load flow, stale flows greyed), an interactive maneuver list
(focus / remove / remove-block / reset), one-click Simulate into a
manual action card, and full combined-action support. Six new replay
events; full contract in docs/features/sld-topology-edit.md.
🎛️ Operator UI consolidation
- Light / dark theme — a true token-swap (single source of truth in
styles/tokens.*), including a legibility pass over the pypowsybl NAD/SLD
chrome and the overflow viewer; no first-paint flash. - Shared Action-Filter rings — severity + action-type + Max-loading
threshold in one sidebar strip that the feed, Action Overview, both
modals and the overflow iframe all read from (so a card hidden in one
place is hidden everywhere). Fixes a silent threshold no-op in two tables. - Readability-first sidebar — the contingency picker and the
(renamed) Remedial Actions feed swap at trigger; a sticky-banner
Clear shortcut; an overload info bubble that absorbs the retired
OverloadPanel; a collapsible shell that hands width to the diagram. - Notices → one discrete pill (
⚠ Notices N) instead of stacked
banners, operator-dismissed. - Per-stage execution-time breakdown on the "Suggestions produced
by …" line (step1 / graph / prediction / assessment / enrichment +
wall-clock), persisted in sessions — plus a one-load-flow optimization
that reuses the N-1 contingency observation (~1–3 s saved per analysis). - Inspect elements by their displayed name (e.g.
LESQUIVE 400kV),
not just the raw id, across every inspect surface.
▶️ Two new ways to run it
- Game Mode (
?game=1) — a timed, scored wrapper: remediate each
study with ≤ 3 actions before the timer, export agame_session.jsona
Codabench competition scores (60·R + 25·R·A + 15·R·T). Additive and
inert unless enabled. - Online deployment — a one-container HuggingFace Docker Space
serving the SPA same-origin with the backend on :7860 (booting straight
into Game Mode). Binary grids ship via Git LFS, with the large France
225/400 kV grid transparently decompressed fromnetwork.xiidm.zip.
🧱 Under the hood
- Code-quality gate, hardened into a multi-axis guard (new in this
release) — mypy now gates at 0 (aTYPE_CHECKINGshared-state base
lets the recommender mixins type-check as the one class they compose;
zero runtime change), test coverage gates both ends (frontend vitest
thresholds + backendfail_under = 72), and the gate gained
dependency-free cyclomatic-complexity / nesting / logical-LoC /
return-annotation metrics plus ratchets for weak casts and lint
suppressions. The scan now also covers the previously-ungated
recommenders/package. 52 backend return annotations added; frontend
as unknown ascasts 19 → 12. Full record in
docs/architecture/code-quality-analysis.md§§17–22. - Internal decomposition — the action-variant-patch pipeline split out
ofdiagram_mixin.py(1220 → 769 lines) intoservices/diagram/. - Shipped first-run defaults (
config.default.json) so a fresh
checkout (and the Space) opens on a working study.
⚙️ Compatibility
- Requires
expert_op4grid_recommender >= 0.2.4. - Saved 0.7.x sessions reload with legacy-default fallbacks; the step-2
NDJSON contract is additive-only.
Next up: decomposing the files now riding their tightened
size/complexity ceilings — scoped in
docs/proposals/decompose-ceiling-riders.md.
0.7.5 — Pluggable recommendation models`
Feature + polish release headlined by the pluggable recommendation models integration (paired with expert_op4grid_recommender 0.2.2), the new "Combined only" pin filter, and a couple of operator-reported regressions (config-modal stale-write, PyPSA-EUR Mercator layout) that landed on the way.
Highlights
Pluggable recommendation models (PR #145, paired with expert_op4grid_recommender PR #90 / 0.2.2)
The analysis pipeline no longer hardcodes the expert system: it dispatches to any class implementing the RecommenderModel ABC. Three models ship out of the box:
| Name | Label | Requires overflow graph | Best for |
|---|---|---|---|
expert |
Expert system | Yes | Default — rule-based discovery + scoring on every action type. |
random |
Random | No | Sanity-check baseline. Samples uniformly from the action dictionary, augmented with synthetic reconnection / load-shedding / curtailment actions. |
random_overflow |
Random (post overflow analysis) | Yes | "Is the overflow analysis useful?" baseline. Samples uniformly inside the expert-reduced action space (rule filter + overflow paths + network existence). |
- Selecting a model is a one-dropdown gesture in Settings → Recommender. The parameter inputs render dynamically from each model's
params_spec()so the UI hides knobs the active model doesn't consume. - The Compute Overflow Graph (step 1) toggle is locked-on for models that require it (
requires_overflow_graph=True) and editable for the others — letting the operator opt in to the overflow analysis even with the Random model. - The active model is persisted in
session.jsonunderanalysis.active_model(backend ground truth) andconfiguration.model(operator intent at save time); same split forcompute_overflow_graph. - Third-party models plug in with three lines of code — implement the ABC, decorate with
@register, ensure import. The frontend picks them up automatically viaGET /api/models. See the new Plug Your Own Recommendation Model section in the README.
"Combined only" pin filter
New pin-scoped filter on both the Action Overview tab and the Overflow Analysis iframe sidebar. When enabled, the pin layers render combined pairs plus their two constituents (dimmed for context) and drop every other unitary / un-simulated pin — the Action Feed cards remain unfiltered. Round-tripped through the existing cs4g:filters postMessage envelope so both surfaces stay in lock-step.
Config-modal stale-write fix
Switching the config-file path and clicking Apply now actually sends the freshly loaded config to /api/config. The previous behaviour silently sent the previous render's closure values, which the auto-save effect then persisted back into the freshly loaded file — undoing the operator's selection.
PyPSA-EUR grid layouts use raw Mercator metres
The previous 8 000-unit rescaling default forced pypowsybl VL circles to overlap in dense regions like Paris. Default behaviour is now raw projected metres (~1.4 M span for the French grid); pass --target-width N to reproduce the legacy rescaled output.
Added
- Recommender model registry (
expert_backend/recommenders/):registry.py,random_basic.py,random_overflow.py,synthetic_actions.py,overflow_path_filter.py,network_existence.py,_service_integration.py. GET /api/modelsendpoint — returns the full list of registered recommenders with theirparams_spec(), label and capability flags.ConfigRequest.model/ConfigRequest.compute_overflow_graphfields, echoed asactive_model/compute_overflow_graphin the finalresultevent of the step-2 NDJSON stream.- Saved session model echo —
session.analysis.active_model(backend ground truth) +session.configuration.model(operator intent), same split forcompute_overflow_graph. - Frontend types and hooks —
ModelDescriptor/ModelParamSpec,recommenderModel/computeOverflowGraph/availableModelsstate inuseSettings, dynamic dropdown + locked-vs-optional toggle states inSettingsModal, action-card VL chip readsaction_topology.voltage_level_id(so OPEN / CLOSE coupling cards double-click-zoom to the correct VL). - "Combined only" pin filter on the Action Overview tab and the Overflow Analysis iframe.
docs/backend/subfolder —README.md(broader backend overview) andrecommender_models.md(relocated fromdocs/recommender_models.mdwith app-side integration + filter chain + step-by-step guide).- "Plug Your Own Recommendation Model" section in the root
README.md. - Backend tests —
tests/test_recommenders_registry.py,test_random_recommenders.py,test_model_selection_mixin.py,test_service_integration.py,test_models_api.py,test_network_existence.py,test_overflow_path_filter.py,test_action_enrichment.py.
Changed
extract_action_topologyrobustness (expert_backend/services/analysis/action_enrichment.py): backfills emptylines_or_bus/lines_ex_bus/gens_bus/loads_busfromdict_action[id].content.set_bus, surfacesvoltage_level_id, and tolerates numpy arrays via a new_is_meaningful_dicttruthy-check. Fixes pins stacking onmax_rho_linewhen running the Random model.build_recommender_inputspropagation: the expert-rule filter result (context["filtered_candidate_actions"]) is now forwarded to the DTO so sampling models actually see the filtered pool — caught a silent bypass whereRandomOverflowRecommenderran against the full action dictionary while the filter was running upstream.overview_filter_changedinteraction-log event now carries acombined_onlydiscriminator.
Fixed
- Settings modal stale-write on config-file switch:
changeConfigFilePathnow returns the resolvedUserConfig, andconfigRequestFromUserConfigderives the request from it. Regression test infrontend/src/App.configUpload.test.tsx. - PyPSA-EUR grid-layout rescaling — default is now raw Mercator metres.
data/pypsa_eur_fr225_400/grid_layout.jsonanddata/pypsa_eur_fr400/grid_layout.jsonregenerated. - Action overview pin localisation for non-disconnection actions (Random / Random Overflow runs): pins are now anchored on the action's voltage level rather than the contingency
max_rho_line. numpy.str_comparison crash in_resolve_node_to_nameon legacy distribution graphs.
Documentation
docs/features/save-results.md—model/active_model/compute_overflow_graphfield tables + new "Recommender model persistence" section.docs/features/interaction-logging.md—model/compute_overflow_graphadded toconfig_loaded/settings_applied;active_model/compute_overflow_graphadded toanalysis_step2_completed; new "Pluggable recommender model" section.docs/backend/README.md— NEW: backend overview (architecture, mixins, data flow, conventions, endpoints, tests).docs/backend/recommender_models.md— NEW (relocated): app-side integration + filter chain + step-by-step guide.README.md— NEW "Plug Your Own Recommendation Model" section.
Compatibility
modelandcompute_overflow_graphdefault to"expert"andtrueat every entry point that lacks them (older session dumps, missing form values, third-party callers that didn't update their request shape) — byte-for-byte the same behaviour as 0.7.0.- Frontend dynamic UI from
params_spec()— adding a model requires zero UI code; the dropdown and parameter inputs refresh automatically. - Step-2 NDJSON contract unchanged —
active_modelandcompute_overflow_graphare additive fields on the existingresultevent. - Requires
expert_op4grid_recommender>=0.2.2(for theRecommenderModelABC, theRecommenderInputs/RecommenderOutputDTOs, the reusable reassessment phase and the idempotent_run_expert_action_filterhelper). Older versions raise anImportErrorfromexpert_op4grid_recommender.models.baseon backend startup.
Install
pip install "co_study4grid==0.7.5" "expert_op4grid_recommender>=0.2.2"See CHANGELOG.md § 0.7.5 for the full entry.
Full changelog: marota/Co-Study4Grid@0.7.0...0.7.5
Generated by Claude Code
0.7.0 — interactive overflow analysis tab + PyPSA-EUR + design tokens
Major feature release headlined by the interactive overflow analysis tab, the PyPSA-EUR European-wide grid pipeline, and a full design-token migration of the frontend.
Re-tagged 2026-05-05 at commit
a6bbe40to fold in the post-initial-tag pin-overlay fixes (PR #129). The 0.7.0 release artefact now points at the merge that ships the working pin overlay; the original519ad61tag is gone.
Highlights
Interactive overflow analysis tab (PRs #116, #122–#127, #128, #129)
The static overflow PDF is replaced by a same-origin HTML viewer produced by upstream alphaDeesp/core/interactive_html.py:
- Layer-toggle sidebar grouped into three sections — Structural Paths (Constrained path, Red-loop), Individual entities properties (Overloads, Low-margin lines, Hubs, Reconnectable, Non-reconnectable, Swapped flow, Production nodes, Consumption nodes) and Flow redispatch values (Positive / Negative / Null).
- Hierarchical ↔ geographic layout toggle backed by a per-study cache.
- Action-pin overlay synced with the Action Overview filters — single-click pins open the same
ActionCardPopover, double-click drills into the SLD overlay. Pins land on the actual visual mid-arc of the rendered Bézier edge (getPointAtLength(len/2)), spread on a small circle when colocated, and combined-action pairs render a dashed Bézier connector between the two unitary halves with a+badge on the midpoint glyph. - Filter-driven dimming, mirroring
ActionOverviewDiagram's three-pass pipeline: a unitary action that fails the active filter is rendered withdimmedByFilteropacity 0.35 (instead of being dropped) when a passing combined-action pin references it as a constituent. - Sidebar filter chips match the React
CategoryTogglevisual: no blue solid fill on selected, dim the unselected ones, swatch-coloured border on the active chip. - Auto-installer for the graphviz
dotbinary on package install (PR #126). - Six new replay-log event types:
overflow_layer_toggled,overflow_select_all_layers,overflow_node_double_clicked,overflow_pin_clicked,overflow_pin_double_clicked,overflow_pins_toggled,overflow_layout_mode_toggled.
PyPSA-EUR European-wide grid (PRs #112, #117)
Full pipeline in scripts/pypsa_eur/ for generating XIIDM grids from PyPSA-EUR data, with calibrated thermal limits, an fr225_400 dataset, and pytest coverage.
Design-token migration (PR #120, three phases)
frontend/src/styles/tokens.{css,ts} is the single source of truth for colour, spacing, typography and radius. Code-quality gate enforces FRONTEND_HEX_LITERAL_MAX = 0 outside the token files.
UI polish
- Tiered warning system + diagram legend (PR #122): structured notice tiers and an in-place legend on the Visualization panel.
- Progressive-disclosure ActionCard (PR #121): severity icons drive a glanceable summary; details expand on demand.
- Voltage-level names toggle (PR #118):
🏷 VLchip with a native<title>tooltip fallback.
Merged PRs since 0.6.5
| PR | Title |
|---|---|
| #112 | feat: PyPSA-EUR pipeline consolidation, fr225_400 dataset, full test coverage |
| #113 | Remove unnecessary f-string prefixes from static strings |
| #114 | Surface target max rho on user-selected overloads in pair estimation |
| #115 | docs: Update CLAUDE.md, README.md, and backend/frontend guides for 0.6.5 |
| #116 | feat(overflow): interactive HTML viewer + Hierarchical/Geo toggle + N-1 disconnect fix |
| #117 | feat(pypsa-eur): support European-wide grid generation |
| #118 | Add voltage-level names toggle with native tooltip fallback |
| #119 | docs: add development-cycle retrospective (4 phases) |
| #120 | feat(frontend): design-token migration (recommendation #1) |
| #121 | Redesign ActionCard with progressive disclosure and severity icons |
| #122 | Implement tiered warning system and diagram legend (UI critique #4-5) |
| #123 | Fix NoticesPanel popover clipping by rendering via portal |
| #124 | feat(overflow): interactive overflow analysis tab |
| #125 | Document Overflow Analysis tab interactions and ephemeral UI state |
| #126 | Add Graphviz auto-installer and pydot dependency for graph rendering |
| #127 | fix(build): restore quality extras under optional-dependencies |
| #128 | Mid-arc anchoring + Action-Overview-style pin layout (initial pin overlay) |
| #129 | Pin overlay fixes: duplicate const, dimmedByFilter, protectedIds, chip restyle |
See CHANGELOG.md § 0.7.0 for the full entry.
Co-Study4Grid 0.6.5
Follow-up release to 0.6.0 consolidating four strands of post-0.6.0 work merged across PRs [#111](https://github.com/marota/Co-Study4Grid/pull/103) → [#111](https://github.com/marota/Co-Study4Grid/pull/111):
⚡ Performance — SVG DOM recycling on N-1 / Action tabs ([PR #108](https://github.com/marota/Co-Study4Grid/pull/108))
Stop re-fetching and re-parsing the full pypowsybl NAD SVG (12–28 MB) on every N-1 / Action tab change. The new /api/n1-diagram-patch and /api/action-variant-diagram-patch endpoints return only the per-branch delta; the frontend clones the already-mounted N-state SVGSVGElement and patches it in place — dashed contingency lines, absolute flow labels, concentric rings for coupling / node-merging / node-splitting actions.
Measured on the French grid benchmark (bare_env_20240828T0100Z, ~10 k branches, contingency ARGIAL71CANTE, warm median of 3):
| Endpoint | Cold | Warm | Payload |
|---|---|---|---|
/api/n1-diagram (full) |
3.01 s | 2.39 s | 27.1 MB |
/api/n1-diagram-patch (new) |
0.49 s | 0.50 s | 5.5 MB |
| Δ | −83.8 % | −79.1 % | 20.3 % of full |
Graceful full-NAD fallback on every unsupported edge case (session reload, mount race, extraction failure). Docs: [docs/performance/history/svg-dom-recycling.md](https://claude.ai/code/docs/performance/history/svg-dom-recycling.md).
🎯 Action Overview — filtering & unsimulated pins ([PR #105](https://github.com/marota/Co-Study4Grid/pull/105), [#107](https://github.com/marota/Co-Study4Grid/pull/107))
- Severity category toggles (green / orange / red / grey), threshold slider, action-type chip filter and a new unsimulated pin layer for scored-but-not-yet-simulated actions (dimmed, dashed, double-click to simulate).
- Filter state is shared between the overview pins and the sidebar action feed, so both views stay in lock-step. New
actionPassesOverviewFilter()predicate +classifyActionTypemodule unify the filtering logic across three UI surfaces. - Protected constituent pins: when a combined action passes the filter, its unitary parts stay visible (dimmed) even if they individually fail, preserving context.
🧪 Code-quality gate + decomposition sweep ([PR #104](https://github.com/marota/Co-Study4Grid/pull/104), [#106](https://github.com/marota/Co-Study4Grid/pull/106))
New continuous quality reporter (scripts/code_quality_report.py) and CI gate (scripts/check_code_quality.py) guarding LoC ceilings + smell counts. Metrics drive five behaviour-preserving decomposition passes:
| Target | Before | After |
|---|---|---|
simulate_manual_action |
599 LoC | 146 |
compute_superposition |
285 LoC | 108 |
frontend/src/utils/svgUtils.ts |
1807 LoC | 60 barrel + 8 focused modules |
analysis_mixin.py |
1116 LoC | 509 + 4 modules |
diagram_mixin.py |
974 LoC | 469 + 7 modules |
Public API unchanged; @patch compatibility preserved via dependency injection; 230+ new unit tests across the extracted helpers. CI publishes the Markdown metrics to $GITHUB_STEP_SUMMARY.
🧹 Frontend refactor — App.tsx hook extraction ([PR #109](https://github.com/marota/Co-Study4Grid/pull/109))
- New
hooks/useN1Fetch.ts(svgPatch fast-path +/api/n1-diagramfallback + contingency-change confirm routing). - New
hooks/useDiagramHighlights.ts(per-tab Flow/Impacts view-mode +applyHighlightsForTabDOM pass). - Sidebar extracted into
components/AppSidebar.tsx,SidebarSummary.tsx,StatusToasts.tsx. - Unified
ActionTypeFilterChipscomponent reused by Manual Selection, Explore Pairs, Action Feed and Action Overview. App.tsx: 1575 → ~1150 lines.
📚 Docs reorganisation ([PR #103](https://github.com/marota/Co-Study4Grid/pull/103))
Flat docs/ restructured into docs/{features,performance/{,history/},architecture,proposals,data}/ with per-folder README.md indexes. Three overlapping rendering-LoD proposals consolidated into [docs/proposals/rendering-lod-strategies.md](https://claude.ai/code/docs/proposals/rendering-lod-strategies.md). All cross-references in source, tests, benchmarks, scripts and CI workflows updated.
🐛 Fixes worth calling out
- Dynamic
reco_reconnection actions: reconnection actions generated byexpert_op4grid_recommenderbut absent from the loaded action dictionary (e.g.reco_CAZARL72MARSIfrom the Explore Pairs tab) now simulate correctly, via the same dynamic-creation path already used forcurtail_ / load_shedding_ / pst_. - Combined
disco + couplinghalo restored on the disco line in the combined action (PR #108). - Blank flash + stale-response guard on svgPatch for large grids (PR #108).
- Node-merging classifier: "Ouverture … dans le poste" is now DISCO, not OPEN coupling (PR #105).
- Popover viewport + combined-pin constituent protection (PR #105).
See [CHANGELOG.md](https://claude.ai/code/CHANGELOG.md) for the full, sectioned list.
Full changelog: marota/Co-Study4Grid@0.6.0...0.6.5
# Co-Study4Grid 0.6.0 — 2026-04-20
Released 2026-04-20
Follow-up release to 0.5.0 consolidating the standalone-parity
effort, the Action Overview diagram, inactive-tab SVG perf work,
and the docs reorganisation.
Highlights
- Auto-generated single-file standalone (
npm run build:standalone)
replaces the hand-maintainedstandalone_interface.html. The React
source infrontend/src/is now the single source of truth — no
manual mirroring required when adding a component, setting, API
call, or gesture. - Layer-4 user-observable invariants — runtime Vitest twin
(userObservableInvariants.test.ts) paired with
scripts/check_invariants.py, guarding the six classes of
regression that had previously shipped past layers 1–3. - Action Overview diagram — map-pin overlay on the N-1 NAD
showing every prioritised action with severity colouring and
pan/zoom-aware pin rescaling. - Perf:
display:noneon inactive SVG tabs cuts live DOM nodes
from ~600 k to ~200 k on the French grid. - Docs reorganised into
features/,performance/(+
history/),architecture/,proposals/,data/with a
consolidated rendering-LoD proposal.
Added
- Auto-generated standalone bundle (PR #101): React + CSS
inlined intofrontend/dist-standalone/standalone.htmlvia
vite-plugin-singlefile. Canonical distribution artifact. - Layer-4 parity guard:
scripts/check_invariants.pyfor the
standalone andfrontend/src/utils/userObservableInvariants.test.ts
for the React side. - Layer-3 Playwright E2E suite (
scripts/parity_e2e/e2e_parity.spec.ts)
and a gesture-sequence static proxy (scripts/check_gesture_sequence.py). - Action Overview diagram: severity threshold parameterised by
monitoringFactor, topology-first pin anchoring, combined-pair
dashed curves, Overview backdrop dim, auto-switch to Action tab on
"Display Prioritized". Seedocs/features/action-overview-diagram.md. - Detached + tied visualization tabs brought to full Layer-1
parity (save-only rho arrays, tied viewBox sync,
detach-in-Overview-mode support). /api/simulate-and-variant-diagramstreaming endpoint —
NDJSON{type:"metrics"}then{type:"diagram"}so the sidebar
updates ahead of the SVG.frontend/PARITY_AUDIT.md— working record of the parity
effort, split out of the rootCLAUDE.md.
Changed
- Docs reorganised into
docs/{features,performance/{,history},architecture,proposals,data}/
with per-folder README indexes. Three overlapping rendering-LoD
proposals merged intodocs/proposals/rendering-lod-strategies.md.
All in-repo references updated acrossCLAUDE.mdfiles,
README.md, benchmarks, scripts, tests and source comments. expert_backend/CLAUDE.md/frontend/CLAUDE.mdrefreshed
with the post-decommission wording (single source of truth in
frontend/src/).
Performance
display:noneon inactive SVG tabs (PRs #99, #102): the
off-screen N / N-1 / Action SVGs drop from the browser paint tree,
cutting live DOM nodes from ~600 k to ~200 k on the French grid.
Seedocs/performance/history/svg-tab-unmount.md.
Fixed
- SLD highlight for LS / curtailment / PST targets on the Action
tab, with a text-search fallback when the metadata index misses an
equipment ID. - Overload halo suppression on "Solved — low margin" actions in
both NAD and SLD. - Session reload now refreshes the N-1 diagram and preserves
action-bucket / combined-pair state without re-simulation;
/api/restore-analysis-contextwired in. - Manual re-simulate refreshes the SLD overlay; modal content
word-wraps correctly. - Pin severity uses
monitoringFactor − 0.05instead of a
hardcoded 0.9 / 1.0 cutoff, fixing the MF = 0.85 misclassification. - Pin anchor uses the topology target (action's disconnected
line) rather thanmax_rho_line. - Rendering fidelity for Overview, detached tabs, overflow tab,
and action auto-zoom. - ESLint errors in
userObservableInvariants.test.ts
(@typescript-eslint/no-explicit-any,no-unused-vars).
Removed
expert_backend/tests/test_ui_regressions.py— its assertions
targeted strings in the decommissionedstandalone_interface.html;
equivalent coverage now lives in the four parity scripts
(scripts/check_*.py) and in the Vitest suite.
Documentation
- New consolidated doc:
docs/proposals/rendering-lod-strategies.md. - New index files:
docs/README.md,docs/performance/history/README.md. docs/features/action-overview-diagram.mdfor the Action Overview
diagram feature.- Root, frontend, and expert_backend
CLAUDE.mdfiles reflect the
auto-generated standalone workflow and the new docs tree.
Upgrade notes
- No migration required for existing sessions —
session.json
format is unchanged. - If you were editing
standalone_interface.htmlby hand, stop:
edit the React source infrontend/src/and run
npm run build:standaloneto regenerate
frontend/dist-standalone/standalone.html. The legacy file is
preserved asstandalone_interface_legacy.htmlfor reference.
Full changelog: https://github.com/marota/Co-Study4Grid/blob/0.6.0/CHANGELOG.md
Compare with 0.5.0: marota/Co-Study4Grid@0.5.0...0.6.0
Co-Study4Grid 0.5.0 — Release Notes
Released 2026-04-14
First tagged release under the Co-Study4Grid name (formerly ExpertAssist). This release consolidates the work merged in PRs #57 → #91 and ships a stable, production-ready contingency-analysis assistant for large grids.
TL;DR
- ~4× faster manual-action simulation on the full French grid (~10k branches)
- ~1,100× faster overload detection, 47× faster delta computation
- Two-step N-1 workflow (detect → select → resolve) as the primary path
- Full remedial-action catalog: topology, PST tap, renewable curtailment, load shedding — individually, manually, or as pairs
- Detachable visualization tabs for dual-monitor studies
- Session save/reload + replay-ready interaction log
- Rebrand ExpertAssist → Co-Study4Grid, MPL-2.0 banners across all sources
Highlights
Performance — Big Grids Now Fly
Measured on the full French grid (~10k branches) with scripts/profile_diagram_perf.py:
| Metric | Before | After | Speed-up |
|---|---|---|---|
| care_mask / overload detection | 12.17 s | 0.01 s | ~1,100× |
| Branch flow extraction | 0.82 s | 0.06 s | ~13× |
| Flow delta computation | 0.47 s | 0.01 s | ~47× |
| get_obs() overhead | 0.65 s | 0.01 s | ~65× |
| Total manual-action simulation | ~16.5 s | ~4.0 s | ~4× |
| Base diagram rendering | ~7.2 s | ~3.5 s | ~2× |
| N-1 contingency analysis | ~19.8 s | ~12.9 s | ~1.5× |
How: NumPy vectorization of the care_mask loop, flow extraction and delta pipelines; observation caching in the manual-action loop; pre-built SimulationEnvironment and dict_action reused across steps; lxml-based NaN stripping + gzip compression for the 13 MB NAD SVG payload; frontend throttling and zoom-tier level-of-detail. Details in docs/PR_PERF_OPTIMIZATION.md and docs/performance_profiling.md.
Workflow — Two-Step N-1 Analysis
The primary user path is now a two-step flow:
/api/run-analysis-step1— detect overloads under the selected contingency.- Operator picks which overloads to resolve.
/api/run-analysis-step2— stream prioritized remedial actions (NDJSON).
The legacy single-shot /api/run-analysis endpoint remains for backward compatibility. AC/DC fallback is transparent — AC load flow first, DC on non-convergence.
Full Remedial-Action Catalog
- Topology: switches, bus reconfiguration, line disconnection / reconnection, close / open coupling.
- Phase-Shifting Transformers (PST) (PR #78): tap start / target columns, re-simulation from the score table, target-tap sync, superposition fallback for PST pairs.
- Renewable curtailment (PR #72) and load shedding (PR #61, #73) using the new
set_gen_p/set_load_ppower-reduction format — elements stay electrically connected, preserving voltage and reactive support. Configurable MW reduction. - Combined actions: evaluate pairs via a fast superposition (beta-coefficient) estimation or an exact full simulation through the Computed Pairs / Explore Pairs modal. LS + RC combinations are restricted in the UI.
See docs/curtailment-loadshedding-pst-actions.md and docs/combined-actions.md.
Visualization — Made for Dual Screens
- Detachable tabs (PR #84/#86/#87/#90): pop any of the four visualization tabs — Network N, Contingency N-1, Remedial Action, Overflow Analysis — into a second browser window. Tie/untie, bidirectional controls, per-window pan/zoom preservation, stable-portal DOM move (no unmount/remount cascades). See
docs/detachable-viz-tabs.md. - SLD impacted-asset highlights (PR #63): clone-behind halos for switches and coupling breakers, robust across pan/zoom and N-1 / action state changes.
- Focused sub-diagrams with configurable depth for inspecting specific voltage-level neighborhoods on large grids.
- Zoom-tier level-of-detail (PR #76): labels, nodes and flow arrows are boosted proportional to
sqrt(diagramSize / referenceSize)so large grids stay legible at any zoom. - Auto-zoom on contingency, newly overloaded line, or action target; sticky compact feed summary; overload-click jumps to the N-1 tab (PR #88).
Sessions & Replay
- Save Results / Reload Session (PR #62 family): export the complete analysis state — config, contingency, actions with status tags, combined pairs, overflow PDF, loading ratios — to a timestamped session folder (
costudy4grid_session_<contingency>_<timestamp>/). Reload restores the UI exactly, without re-simulating. Documented indocs/save-results.md. - Replay-ready interaction log (PR #64): every UI interaction is written to
interaction_log.jsonas a self-contained, timestamped event with correlation IDs for async completions — suitable for deterministic browser-automation replay. Seedocs/interaction-logging.md. - Persistent user configuration (PR #59) stored outside the repo, with a configurable config-file path.
- Confirmation dialogs (PR #83) guard destructive state resets (switching network while a study is loaded, applying settings on an active study).
Frontend Engineering
- App.tsx — Phase 1 refactor (PR #74): from ~2100 → ~650 lines.
App.tsxis now a pure state-orchestration hub; UI extracted into presentational components undercomponents/andcomponents/modals/.useSettingshook exposes a singleSettingsStateobject passed wholesale toSettingsModal. - State management — Phase 2 (PR #75): memoized cross-hook wrappers with
useCallback, centralized reset logic,React.memoon the three heaviest components (VisualizationPanel,ActionFeed,OverloadPanel). Eliminates unnecessary re-renders. - Oversized components split (PR #81) into focused subcomponents with dedicated test suites.
- React
ErrorBoundarywrapping the app root (PR #82). - Standalone single-file UI (
standalone_interface.html) kept in feature lockstep with the React app — zero-install demos.
Notable Fixes
- Second-contingency crash, auto-zoom loss on contingency switch, overload persistence across successive studies (PR #80).
min_renewable_curtailment_actionsmissing from saved config (PR #80).- Auto-zoom double-injection on contingency switch —
MemoizedSvgContainernow kept always mounted (PR #81). - N-1 variant clone made from the clean N state, not the working variant (PR #81).
- Contingency highlight z-ordering: sibling insertion with solid yellow halo, surviving pan/zoom and SLD overlay (PR #71).
- Overload highlight thresholds and loading display values (PR #71).
- Monitoring-factor scaling restored for suggested actions (PR #71).
- Superposition monitoring aligned with
simulate_manual_action; overloaded lines force-included ineligible_mask(PR #79). - PST re-simulation preserves
_dict_actionstructure; additive superposition fallback for PST no-op (PR #78, #79). - Combined-action estimation filtering: heavily loaded N-state lines are no longer incorrectly filtered out (PR #72).
- Backend regressions on
gen_p, observation sequence, legacy keys, and islanding reporting after the manual-action enrichment refactor (PR #72, #73). - Re-simulate double-click bug on action cards (PR #73).
- SLD rendering regressions: blank screen, missing N-1 highlight,
ReferenceErrorcrash in the overlay (PR #76). - Grid layout functionality restored with regression tests (PR #69).
API Changes
New endpoints added in this release:
Analysis
POST /api/run-analysis-step1— two-step flow, step 1POST /api/run-analysis-step2— two-step flow, step 2 (streaming NDJSON)POST /api/simulate-manual-actionPOST /api/compute-superposition
Diagrams
POST /api/action-variant-diagramPOST /api/focused-diagramPOST /api/action-variant-focused-diagramPOST /api/n-sld,POST /api/n1-sld,POST /api/action-variant-sld
Sessions & config
GET /api/user-config,POST /api/user-configGET /api/config-file-path,POST /api/c...