Source document

docs/cities/philly/02_gap_analysis.md

Served verbatim from the project repository. Internal working document conventions apply: documents may reference file paths, branch names, and findings-ledger anchors from the repo.

02 — Gap Analysis (Philly source layer vs. NYC)

How the Philly build differs from the NYC build, dimension by dimension. Same format as docs/design/02_gap_analysis.md (KX's NYC gap analysis), so the direct comparison is legible.

Each row scores what changes to port the corresponding NYC capability to Philly. "Same" = lift verbatim; "Adapt" = config or schema tweak; "New" = code that has no NYC analogue.


A. Source ingest

#DimensionNYC posturePhilly postureChange
A.1Source connector kindxlsx via NYC DOE InfoHub CDNMix of Socrata API (OpenDataPhilly) + xlsx via PDEAdapt. New Python connector for Socrata; keep xlsx connector.
A.2School-roster join keyDBN (e.g. 10X440)PDE 9-digit Public School Code as primary; SDP School ID as joinNew. Primary-key migration; carry both IDs.
A.3Year encodingYYYY-YY (e.g. 2024-25)PDE uses YYYY-YY; SDP uses both YYYY-YY and end-year-intSame. Loader normalizer handles both already.
A.4Suppression rulen < 5 (DOE), n < 10 (NYSED)n < 11 (PDE)Adapt. Threshold in outcomes.yaml.
A.5File-bytes provenancesha256 + retrieved_at + bytes via verify/download.pySame connector pattern works on PDE xlsx; Socrata pulls record response metadataSame. KX's download.py extends to Socrata directly.
A.6Source-file refresh URL stabilityInfoHub URLs are stable but unversionedOpenDataPhilly Socrata URLs are stable; PDE URLs are stable per datasetSame posture. Annual full re-pull.

B. Schema (Postgres)

#DimensionNYCPhillyChange
B.1schools tableDBN as primary key; community-district + borough columnsComposite AUN + Schl as primary key (see findings.md §F.1); LEA-level joins via AUN; SDP's AUN = 126515001. Geography: learning_network + city_council_district + zip_code + lat/lng.Adapt. Composite PK exposed as a single school_code = "<AUN>-<Schl>" for convenience; carry both columns.
B.2school_type enumDOE_PUBLIC, CHARTER, D75_SPECIAL_ED, D79_TRANSFER, ALT_PROGRAMPDE's actual enum (findings.md §F.5): regular, charter, compctc, cyber, specialed. Renaissance Charter status is not a PDE category — carry it as a derived is_renaissance boolean from the SDP charter office list.Adapt. Adopt PDE's 5-value enum + is_renaissance derived column; do NOT invent SPECIAL_ADMISSION here (that's an admission category).
B.3admission_category enumZONED, OPEN, SCREENED, AUDITION, LIMITED_UNSCREENED, EDOPT, SPECIALIZED_HS, etc.Simpler: NEIGHBORHOOD, CITYWIDE_LOTTERY, SPECIAL_ADMISSION, CHARTER_LOTTERY, MAGNETAdapt. Smaller enum.
B.4subgroup enumALL, ASIAN, BLACK, HISPANIC, WHITE, MULTI_RACIAL, MALE, FEMALE, ELL, FORMER_ELL, NEVER_ELL, SWD, NON_SWD, ECON_DIS, NOT_ECON_DIS, TEMP_HOUSINGPDE actual (from findings.md §F.2): ALL, AMER_INDIAN_AK_NATIVE, ASIAN, HAWAIIAN_PAC_ISL, BLACK, HISPANIC, WHITE, TWO_OR_MORE_RACES, ECON_DISADV, ELL, SWD, COMBINED_ETHNICITY. No gender, no temp-housing, no former-ELL.Adapt. Richer racial granularity than NYC (Amer Indian, Hawaiian/Pac Isl separate); narrower on gender + status subgroups.
B.5school_year_metrics long-format tableOne row per (school, year, metric_key, subgroup, value, suppressed, n)Same. Pattern works identically; loader unpivots Future Ready's wide-format <Measure>_<Subgroup> columns.Same.
B.5aFirst-class essa_designation column on schools(NYC doesn't have it)Per findings.md §F.3: 5-value enum DFLT/TSI/CSI/ATSI/ACSI; updated annually; analytically substantive (53 Philly schools are CSI, 9 are ACSI).New column. Belongs in schools, not as a story tag.
B.5bFirst-class PVAAS growth indicator(NYC doesn't have it)Future Ready exposes PVAAS growth per subject × subgroup (findings.md §F.2). Status-vs-growth decision (NYC's spec §9.3) is settled here by data availability.New metric family. pvaas_growth_* keys; v1 includes at least Algebra/Lit/Bio.
B.6metric_definitionsOne row per metric_keySame structure; ~90 metric_keys for PSSA grades × subjects + Keystone + grad + absenteeism + PSES rollupsSame. Populated by an analog of metric-definitions.ts.
B.7Peer-group tables (peer_groups, school_peers)KNN(K=40) on grade band + admission + demographics + topicSame algorithm; smaller N (~300 vs ~1,800) means k might want to drop to 20–30 for stabilitySame code; revisit k in config.
B.8Survey raw tableOne row per (school, year, question_id, respondent, value, n_respondents)Same. PSES Zip files unpack to the same shape.Same.

C. Analysis pipeline (Python, per KX's 03 §B)

#CapabilityStatus in NYCPhilly change
C.1pipeline/analysis/engine.py (WLS + standardize + flag)Lifted from scaffold; per specSame. No PA-specific logic.
C.2pipeline/analysis/outliers.py, run_outcome.pyLiftedSame.
C.3pipeline/analysis/trends.py + comparability regimesLifted; comparability.yaml configures regime breaksAdapt. Three regime breaks for PSSA: 2014-15 (PA Core), 2022-23 (post-COVID recalibration).
C.4pipeline/assemble/build_analysis_table.pyDB query → parquetAdapt. Same shape, queries Philly schema.
C.5Outcome configs (outcomes.yaml)8 outcomes (ela_g3, math_g3, ela_g7, math_g7, ela_all, math_all, grad_4yr, chronic_absent)New file. ~12 outcomes: PSSA g3-8 ELA, PSSA g3-8 Math, Keystone Alg/Lit/Bio, grad_4yr, chronic_absent.
C.6Covariate configs (covariates.yaml)Race composition, enrollment, admissionSame covariate types; values differ.
C.7Composites on standardized residuals (C5 in NYC plan)Deferred (last)Same sequencing.

D. Validation harness (verify/ analog)

#CapabilityNYC posturePhilly posture
D.1(i) Completenessverify/reconcile.py reports source-only DBNsSame. Reports source-only PDE codes.
D.2(ii) Base caseDB vs exact ingested xlsx (per-cell fidelity)Same mechanism; PDE / OpenDataPhilly source files.
D.3(iii) Spot checkDB vs NYC School SnapshotUse SPREE as the (iii) reference. SDP's SPREE composite is the Philly analogue. Per-metric mappings in snapshot.yaml-equivalent.
D.4(iv) Computed valuesNot done in NYC build eitherSame gap. Deferred.
D.5Independent-publisher referenceDeferred (NYSED)Available day one — PDE and Future Ready PA Index. Use PDE bulk file as the (ii) source-of-truth and Future Ready PA Index as a third reference for cross-checking SPREE.

E. Front-end & UX

#SurfaceNYC changePhilly change
E.1Outliers pageDirection-adjusted percentile, peer/city pills, proclivity badgeSame components; copy needs Philly terminology (Learning Network not District 15, etc.).
E.2Movers pageYear-over-year delta with metric-aware directionSame.
E.3School profile pageOne outcome card per metric × subgroup × peer groupSame.
E.4Stories54 hand-written analyses keyed to NYC programs (Renewal, Small Schools, D15)All new. ~25 Philly-specific story stubs at v1 launch (see §G).
E.5Methodology recipesOne recipe per story + Outliers + MoversSame infrastructure; new content.
E.6Geography taxonomyBorough + community district badgesAdapt. Learning Network + city council district.

F. Stories — the new analytical surface area

Philly has its own program history that maps to interesting analytical questions. Drafted as story stubs, replacing the NYC equivalents:

Philly storyNYC analogue
The Hite closures retrospective (2013) — 23 schools closed during Hite tenure; where did the kids land, what happened to outcomes?NYC Renewal Schools postmortem
Mastery / Renaissance Charter conversion trajectory — schools converted 2010–2015 from district to Renaissance Charter; do their outcomes diverge from a matched-comparison set?NYC Small Schools legacy
Special Admission high schools (Masterman, Central, etc.) — Philly's "specialized HS" analogue; selection effects + value-addNYC SHSAT story
Cyber-charter outcome cliff — students leaving Philly district to cyber-charters; per-student outcome trajectory if cohort data permits(no analogue; new)
Lottery-vs-screened middle schools — Philly's special-admission middle schools (Masterman, GAMP, etc.) compared with neighborhood schoolsNYC D15 screen-vs-lottery
Climate-survey vs outcomes — same template, PSES instead of NYCSSNYC Teacher Voice Attendance story
Charter sector outcome composition — district vs charter, adjusted for student-body(NYC has it as a small piece; Philly is the main story)
Asian achievement variance — Philly's South Asian + East Asian populations have different outcome distributionsNYC equivalent
......

The 25 stubs are populated in docs/cities/philly/stories/ after P3 ships (see 03_integration_plan.md).

G. Bottom line

  • Source layer: mostly new code (Socrata + PDE connectors), shaped by KX's verify/sources.yaml pattern.
  • Schema: structurally the same; enums and PK change.
  • Analysis pipeline: lifted verbatim from the scaffold.
  • Verification harness: lifted; spot-check reference changes from NYC Snapshot to SDP SPREE.
  • Front-end: lifted; copy + geography taxonomy adapt.
  • Stories: all new.

Estimated relative effort vs. NYC build: ~40% of the NYC effort. Smaller universe, fewer source publishers, the methodology is solved, and the verification spine + UI components carry over.