Skip to content

Add CLAUDE.md documentation for ExpertAssist project - #2

Merged
marota merged 1 commit into
mainfrom
claude/claude-md-mlmp9atfefaj8k8n-EVU4j
Feb 14, 2026
Merged

marota merged 1 commit into
mainfrom
claude/claude-md-mlmp9atfefaj8k8n-EVU4j

Conversation

@marota

@marota marota commented Feb 14, 2026

Copy link
Copy Markdown
Collaborator

Summary

This PR adds comprehensive project documentation in the form of a CLAUDE.md file, providing a complete reference guide for the ExpertAssist power grid contingency analysis application.

Changes

  • Added CLAUDE.md: A 160-line documentation file covering:
    • Project overview and purpose (N-1 contingency analysis for power grid operators)
    • Complete monorepo architecture with directory structure
    • Full tech stack details (FastAPI backend, React 19 frontend, pypowsybl, grid2op)
    • Development workflow instructions (backend/frontend setup, build, test commands)
    • Complete API endpoint reference table
    • Key architectural patterns and conventions for both backend and frontend
    • Data flow explanation
    • Dependency lists
    • File naming conventions
    • Important notes for AI assistants and future developers

Purpose

This documentation serves as a single source of truth for understanding the ExpertAssist codebase, enabling faster onboarding and providing clear guidance on:

  • How to run the application locally
  • API contract and usage patterns
  • Code organization and conventions
  • Testing procedures
  • Known limitations and non-portable configurations

The document is structured to be useful for both human developers and AI assistants working with the codebase.

https://claude.ai/code/session_01Y9w9cky5CKAqLnfXneCpon

Document the codebase structure, tech stack, development workflows,
API endpoints, key patterns, and conventions for AI assistants
working with this power grid contingency analysis application.

https://claude.ai/code/session_01Y9w9cky5CKAqLnfXneCpon
@marota
marota merged commit 6c2dc98 into main Feb 14, 2026
marota added a commit that referenced this pull request Apr 18, 2026
After the network_service<->recommender_service mutualisation
(docs/perf-shared-network.md, commit f4184d6), the .xiidm file was
still being parsed TWICE by pypowsybl during /api/config:

  1. network_service.load_network() (already mutualised)
  2. setup_environment_configs_pypowsybl() via grid2op backend

On large grids this 2nd parse costs ~1-5 s of redundant CPU.

This commit (paired with upstream commit 58fe2e44 in
expert_op4grid_recommender 0.2.0.post1) eliminates load #2 by
injecting the already-loaded Network instance into the upstream
helper:

  setup_environment_configs_pypowsybl(network=self._base_network)

SimulationEnvironment and NetworkManager already supported the
`network=` branch — only the top-level convenience function needed
the signature extension (see upstream patch).

Thread-safety: three holders now reference the same Network, but
the variant-mutating operations (grid2op LF in analysis/simulation,
recommender variant switching) don't overlap with /api/config's
NAD worker — confirmed by the v9 trace showing the NAD prefetch
completes before /api/config returns.

Expected impact (v10 trace pending):
  - /api/config: ~16.6 s -> ~13-14 s (-3 s)
  - /api/network-diagram: ~380 ms (unchanged, cache still warm)
  - Total critical path: ~18 s -> ~15 s (-3 s vs v9, -6 s vs v7)

Requires expert_op4grid_recommender >= 0.2.0.post1.

See docs/perf-grid2op-shared-network.md.
marota pushed a commit that referenced this pull request Apr 20, 2026
Three user-facing session-reload regressions fixed in one pass:

1. **N-1 diagram not refetched on reload** — the N-1 effect in
   `App.tsx:724-775` used `hasAnalysisState()` as part of its
   early-return short-circuit. After a session reload actions are
   already rehydrated, so `hasAnalysisState() === true` while
   `n1Diagram === null` — the effect would return early and leave
   the N-1 tab blank, the N-1 Overloads panel empty and the user
   with a dangling "Select a contingency element" placeholder.

   Fix: the early-return now also checks `!restoringSessionRef.current`
   so a just-restored session always proceeds to the fetch.
   `useSession::handleRestoreSession` already flipped the ref to
   `true` before `setSelectedBranch` — a new regression test in
   `useSession.test.ts` locks that ordering in place.

2. **State wiped by `clearContingencyState()`** — once the early
   return is relaxed, the effect reached the `clearContingencyState()`
   + `setN1Diagram(null)` + `setActiveTab('n-1')` block, which would
   wipe the just-restored result / selectedActionIds / overflow PDF
   URL / action diagram. Fix: capture the flag in a local `isRestoring`
   BEFORE resetting `restoringSessionRef.current`, then skip the
   clear + tab switch when restoring.

3. **Overflow PDF appeared unreloaded** — was a downstream symptom
   of #2: `result.pdf_url` got nuked alongside the rest of the
   analysis state. The same skip now preserves it.

Legacy standalone decommissioned:

- `standalone_interface.html` → renamed to
  `standalone_interface_legacy.html`, untracked via `.gitignore`,
  kept on disk for reference only. The canonical single-file
  distribution is now `frontend/dist-standalone/standalone.html`
  produced by `npm run build:standalone`. No more manual mirroring.
- CLAUDE.md (root + frontend) + `docs/save-results.md` updated.
- Four parity scripts default-target the auto-generated bundle and
  fall back to the legacy file when the auto-gen is not built. The
  invariants script maps the legacy `"file_hint"` transparently to
  whichever artifact is on disk.
- Deleted `cssRegression.test.ts` and `standaloneInterface.test.ts`
  (both tested properties of the decommissioned legacy file; the
  React source covers the same invariants and the auto-gen bundle
  inherits them).

New regression tests:

- `useSession.test.ts`: verifies `restoringSessionRef.current` flips
  to `true` BEFORE `setSelectedBranch` fires, locking the ordering
  that makes the N-1 fetch work on restore.
- `SldOverlay.test.tsx` (4 new specs):
  - LS load cell highlighted via `load_shedding_details` fallback
    when `action_topology` is empty
  - Curtailed generator highlighted via `curtailment_details` fallback
  - PST highlighted via `pst_details` fallback
  - Signature cache invalidates when `shedded_mw` bumps in-place
    (re-simulation) — forces clone re-plant on fresh magnitude

Test suite: 936/936 passing (43 files; the 54-test drop vs. last
commit is the two deleted legacy-file tests).
Parity layers: L2 + L4 exit 0; L1 + L3a report the 3 pre-existing
false positives (config_loaded / settings_applied bare-identifier
paths; `reactExports.useCallback` anchor limit) documented in the
CLAUDE.md audit delta.

https://claude.ai/code/session_014N3uuxctcVVocMwxp4EcNL
marota pushed a commit that referenced this pull request May 2, 2026
Adds two layers of regression guards covering all five
recommendations from `docs/proposals/ui-design-critique.md`:

1. Seven new static invariants in `scripts/check_invariants.py`
   (Layer 4):
   - notices_panel_in_sidebar — AppSidebar mounts <NoticesPanel>
   - action_feed_no_dismissable_warning_state — ActionFeed lost
     setShowActionDictWarning / setShowRecommenderWarning
   - overload_panel_uses_monitoring_hint — OverloadPanel exposes
     `monitoringHint`, not the legacy banner props
   - diagram_legend_on_each_diagram_tab — VisualizationPanel wires
     <DiagramLegend tabId="n|n-1|action">
   - nad_overload_halo_capped_at_zoom — App.css caps overload halo
     stroke at 24px on detail-zoom via vector-effect: non-scaling-
     stroke
   - design_token_gate_blocks_inline_hex — FRONTEND_HEX_LITERAL_MAX
     stays at 0
   - action_card_progressive_disclosure_gated_by_isViewing —
     ActionCard renders the disclosure subtree under {isViewing &&

   Total: 10 → 17 invariants. All green.

2. New `frontend/src/uxConsistency.test.tsx` (19 specs) — runtime
   contract checks rendering the real components rather than
   mocks. One describe block per recommendation:
   - #1 design tokens: scans inline `style` attributes for raw hex
     literals and asserts none leak from OverloadPanel / AppSidebar
   - #2 progressive disclosure: ActionCard at-rest hides the
     disclosure subtree; isViewing=true reveals it
   - #3 halo cap: re-asserts the App.css rule (cheaper feedback
     loop than the static script)
   - #4 warning tier: OverloadPanel without monitoringHint shows
     no inline yellow banner; ActionFeed at default state has no
     warning-styled descendant; AppSidebar surfaces the
     <NoticesPanel> pill iff notices.length > 0
   - #5 diagram legend: each tab in VisualizationPanel mounts a
     legend pill when its SVG is loaded, omits it when absent
   - source-text invariants: cross-checks the file-level
     contracts so a refactor that drops a recommendation fails
     this file too

   1182 → 1201 specs. All passing; ESLint clean; code-quality
   gate clean.

https://claude.ai/code/session_01EYXsLY6hKRncRxj3KTHERk
marota pushed a commit that referenced this pull request May 7, 2026
Two parity scripts referenced the legacy single-string contingency
event / tab id and started failing once the N-K refactor renamed them:

- ``check_invariants.py`` — invariant
  ``diagram_legend_on_each_diagram_tab`` regex looked for
  ``tabId="n-1"`` but the contingency tab id is now ``"contingency"``.
  Rewriting the chained pattern restores the 17/17 score.

- ``check_gesture_sequence.py`` — gesture #2 (Select contingency)
  expected the legacy ``contingency_selected`` event. The new flow
  splits the gesture into ``contingency_element_added`` /
  ``contingency_element_removed`` (per-chip toggle) plus
  ``contingency_applied`` when the user clicks the Trigger button to
  commit the pending list. The COMMIT is what drives the diagram
  fetch, so the spec now expects ``contingency_applied`` on the
  React side; ``contingency_selected`` stays as the standalone-side
  primary handler with ``contingency_applied`` as a fallback so the
  freshly-built ``dist-standalone/standalone.html`` (carrying the
  new event) wins on CI.

Layer 1 (static parity) needs no script change — the auto-generated
``frontend/dist-standalone/standalone.html`` regenerated by
``npm run build:standalone`` in the CI workflow inherits the new
``/api/contingency-*`` paths and the new InteractionType events
straight from the React source tree.

Verified locally: all five gates (Layer 1 / 3a / 4 + session-
fidelity Layer 2 + code-quality) exit 0.

https://claude.ai/code/session_01CtPJf8fEJAts2tbxBA7cSF
marota pushed a commit that referenced this pull request Jun 18, 2026
Targets #1 + #2 from the code-quality review.

The three mixins (Diagram/Analysis/Simulation) operate on the composed
RecommenderService `self`, so per-class mypy checking false-positived on
every cross-mixin `self._x` (~63 of 69 errors). Declare that shared
surface once in services/_recommender_state.py — a TYPE_CHECKING-only
base the mixins inherit at type-check time and `object` at runtime, so
there is no MRO or behaviour change (confirmed: offline backend suite is
byte-identical stashed vs not — 624 passed either way).

Fixes the 3 real latent type bugs the noise was hiding (#2):
- run_analysis_step2: `list[str]` params defaulting to None → `| None`
- _cached_obs_n1_elements Optional/non-Optional mismatch (resolved by the
  shared declaration)
and scope-disables `method-assign` for the by-design model-integration
method swaps in recommenders/_service_integration.py (rather than adding
`# type: ignore`, which would breach the suppression ratchet).

mypy is now 0 and GATES the build (was advisory); pinned mypy==1.19.* for
CI reproducibility. ruff clean.

https://claude.ai/code/session_0185GQf52QDpMM4zRDmGVN8X
marota pushed a commit that referenced this pull request Jun 18, 2026
Persists the measured scorecard and the outcomes of targets #1/#2/#3/#5/#6
(and the deliberate #4 deferral) in the analysis doc, and bumps the
"Last updated" header.

https://claude.ai/code/session_0185GQf52QDpMM4zRDmGVN8X
marota added a commit that referenced this pull request Jul 3, 2026
Add 2026-07 full-repository review to docs/architecture
marota added a commit that referenced this pull request Jul 3, 2026
Add 2026-07 full-repository review to docs/architecture
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants