# Szpitale-graph — agent instructions **TL;DR:** `cd szpitale-graph && ./mvnw -q compile` (wrapper, not `mvn`). Build lives in `szpitale-graph/`. Neo4j via `docker compose up -d` from same dir. CLAUDE.md has full TDD rules and PLAN2.md has the execution backlog. This file covers what CLAUDE.md doesn't. ## Project location & structure - Application root: `szpitale-graph/` (not the repo root). - All Maven commands run from `szpitale-graph/` using `./mvnw`. - Source: `src/main/java/com/developx/szpitale/` - Tests: `src/test/java/com/developx/szpitale/` (mirror packages) ## Key commands | Task | Command | |---|---| | Compile | `./mvnw -q compile` | | Test single | `./mvnw -q test -Dtest=ClassName` | | All tests | `./mvnw -q test` | | Verify | `./mvnw -q verify` | | Run CLI | `java -jar target/szpitale-graph.jar` | | Neo4j up | `docker compose up -d` | | Neo4j down | `docker compose down -v` | ## Architecture (two layers, JSON between them) ``` ingest (layer 1) ──canonical/*.json──→ load (layer 2 → Neo4j) ``` - **Ingest** = source parsing + normalisation + dedup. No Neo4j dependency. - **Load** = canonical JSON → UNWIND/MERGE into Neo4j. No network dependency. - Canonical files: `canonical/.json` or `canonical/all.json`. ## Code layout (`src/main/java/com/developx/szpitale/`) | Package | Purpose | |---|---| | `model/` | `CanonicalDataset`, `Hospital`, `Person`, `Affiliation`, `Role`, `Mandate`, `RawHospitalRecord` | | `model/enums/` | `LegalForm`, `RoleType`, `MandateType`, `ConfidenceLevel`, `RoleStatus`, `AffiliationType`, `OrganType`, `SupervisoryBodyType` | | `ingest/` | `IngestCommand`, `CanonicalWriter`, `IngestResults` | | `ingest/source/` | `MarkdownRegistrySource` (parses `research-*.md`), `VoivodeshipSource` (interface) | | `ingest/normalize/` | `NameNormalizer`, `PartyNormalizer`, `Deduplicator` | | `load/` | `LoadCommand`, `CanonicalReader`, `GraphSchema`, `GraphLoader`, `GraphValidator` | | `SzpitaleGraphApplication.java` | `@SpringBootApplication` entry point | ## Data format Research files: `research-.md` (e.g. `research-podlaskie.md`). Table header: ``` | Funkcja | Imię i nazwisko | Afiliacja partyjna | Źródło (URL) | ``` Every cell **must** have an `https://...` URL. No URL = `BRAK_DANYCH` or skip. ## Current state: build is broken (T1 blocker) `Deduplicator.java:75` — `groups` is `Map>` but code puts `List`. Fix needed before any test can run. See PLAN2.md §11, task T1. ## Dependencies - Spring Boot 3.4.4 (spring-shell, neo4j-starter, web) - Jackson (databind + jsr310) - Jsoup 1.18.3 (HTML/Mobile Markdown parsing) - Commons Text 1.12.0 (Jaro-Winkler fuzzy match) - Commons CSV 1.12.0 (reports) - Lombok: **declared in pom.xml but has NO `` — add one if you modify it** - Spring Shell: **declared in pom.xml with empty line — needs `` if you enable it** - Testcontainers Neo4j 1.20.4 + JUnit Jupiter ## Test conventions - Tests mirror main package structure. - Class-name based: `./mvnw -q test -Dtest=NameNormalizerTest` - Integration tests (`*IT`) use `@Testcontainers` + `Neo4jContainer`. - Fixture files → `src/test/resources/fixtures/` ## Git / checkpoint protocol PLAN2.md mandates: one checkpoint commit per task (`-m "T: descript [checkpoint]"`). The `local-agent-progress.json` file tracks task states. On conflicts, **git log is the source of truth** (PLAN2.md §13.5). ## Getting a new voivodeship 1. Deep-research → produce `research-.md` in same table format as `research-podlaskie.md` 2. Place file in `old/` or a `research/` directory 3. Run `ingest --voivodeship ` → generates canonical JSON 4. Run `load --voivodeship ` → pushes to Neo4j No code changes needed to add a new region.