Skip to content

Employer–firm relationships: US-first plan, evaluation gates, and two-workstream split #192

Description

@vahid-ahmadi

Employer–firm relationships in Populace (US-first)

📊 Visual plan (live): https://employer-firm-plan.vercel.app

Per Max's ask, this is the plan for attaching job spells with employer attributes to the Populace dynamic person panel — US first, following the ECPS recipe (impute from panel data → calibrate to administrative aggregates) and this repo's evaluation discipline (pre-registered gates, noise floors, one-shot candidate runs). The plan has been through two independent adversarial reviews (a data-claims audit with every source web-verified, and a modeling/precedents review against DYNASIM, MINT, PENSIM, Census SSB/SynLBD, AKM/BLM); rev 1 of the page incorporates both.

Architecture

flowchart LR
  subgraph A["Workstream A — Daphne (person side)"]
    SIPP["SIPP job-level panel<br/>job IDs, tenure, industry,<br/>establishment size (not firm)"]
    CPS["CPS ASEC + tenure supp.<br/>NOEMP = true firm-size label"]
    PSID["PSID / NLSY<br/>long-horizon tenure"]
    IMP["microimpute QRF<br/>spells onto CPS persons +<br/>transition hazards (phase 1)"]
    SIPP --> IMP
    CPS --> IMP
    PSID --> IMP
  end
  subgraph B["Workstream B — Vahid (firm side)"]
    MARG["SUSB · BDS · CBP · SynLBD<br/>firm-type margins & dynamics"]
    FLOW["QWI · J2J · JOLTS · BED<br/>flow & earnings aggregates"]
    REG["BLM firm-type register<br/>(types, not firm IDs)"]
    MARG --> REG
  end
  MATCH["match layer (interface)<br/>C1 spell schema is the contract;<br/>calibrated to QWI/J2J,<br/>disjoint from gate cells"]
  IMP --> MATCH
  REG --> MATCH
  FLOW --> MATCH
  HARNESS["dynamics harness<br/>E1–E12 battery, noise floors,<br/>pre-registered gates"]
  PE["PolicyEngine-US<br/>employer-keyed rules (ESI, mandates)"]
  MATCH --> HARNESS
  MATCH --> PE
Loading

Phasing

  • Phase 0 (static): employer attributes (industry, firm-size class, tenure) imputed onto CPS persons; calibrated to SUSB. Enough for firm-size-threshold policy cross-sectionally.
  • Phase 1 (dynamic): job-spell transition hazards (separation, hire, job-to-job, destination attributes) trained on SIPP, scored against SIPP holdouts, calibrated to QWI/J2J.
  • Phase 2 (two-sided, gated): BLM-style firm-type register — firm types (industry × size × state), not firm identities, since rosters are unidentified from public margins. Goes ahead only if phase-1 gates pass and the E12 identification story holds; otherwise claims scope down to firm-size-keyed policy only.

Evaluation criteria (to be pre-registered, gates.yaml style)

E1–E12 battery (full table on the live page), highlights:

Gate Moment Reference
E1 employment share by firm-size × industry SUSB
E2 separation/hire/J2J rates by age × sex LEHD J2J
E4/E5 employer-retention pairs + multi-window attachment runs (catches chained-model persistence understatement) SIPP holdout
E9 earnings-change distribution conditional on transition type (layering-coherence gate) SIPP holdout
E10 regression gate: existing locked PSID earnings gates must still pass after the spell layer attaches existing gates.yaml
E11 J2J flows by origin × destination firm size (the size ladder) LEHD J2JOD
E12 within/between-firm earnings variance + coworker correlation — the moments that would be wrong under random worker-to-firm assignment bias-corrected AKM (Song et al.; KSS), BDS

Protocol rules from review: calibration cells pre-registered disjoint from gate cells; a SIPP-vs-J2J seam-reconciliation run before thresholds lock; noise floors before any threshold number.

Key review findings already folded in

  1. SIPP 2014+ measures establishment size, not firm size (EJB1_EMPSIZE is location size) → CPS ASEC NOEMP is the firm-size training label.
  2. QWI publishes mean earnings, never medians → E7 restated on means.
  3. QWI/J2J dimensions are pairwise-restricted (firm size XOR firm age; one demographic pair; sub-sector industry × size at state level only).
  4. No one has published a credible synthetic matched US employer–employee file — Census released synthetic persons (SSB) and synthetic establishments (SynLBD) but never the link. Phase 2 would be first; the paper must say so.

Division of labor

Two independent workstreams meeting at three frozen interface contracts (details on the live page):

  • @daphnehanse11 — Workstream A (person side): SIPP job-level reader (label-verified, family.py pattern), CPS NOEMP/tenure loaders, harmonized PSID/NLSY tenure series, QRF spell imputation, phase-1 transition hazards; owns SIPP noise floors and gates E3–E5, E8–E10 plus the seam-vs-J2J reconciliation run. Deliverable to B: the person panel emitting spells in the frozen C1 schema.
  • @vahid-ahmadi — Workstream B (firm side): external-target pipeline (SUSB/BDS/CBP/QWI/J2J/JOLTS/BED extracts committed with provenance notes), canonical firm-size banding decision (C2), calibration with the target/gate partition, BLM firm-type register; owns gates E1, E2, E6, E7, E11, E12 and the aggregate-side floor studies.

Interface contracts: C1 spell schema and C2 canonical firm-size banding freeze in week 1 (changed only by joint PR); C3, the jointly-authored employer gate block, locks after a referee round in week ~4 — no one-shot candidate runs before C3 locks. Sync points are weeks 1, 4, and ~11 (phase-2 go/no-go); everything else is asynchronous — A can develop against fixture spells, B against a synthetic C1-conforming file.

cc @MaxGhenis — process update: plan built, adversarially reviewed twice (data claims + modeling/precedents), revised, split into the two workstreams above, and deployed for browsing at the Vercel link on top. Next concrete step is the week-1 items: readers + ADR (A), target pipeline + banding proposal (B).

🤖 Generated with Claude Code

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions