Skip to content
  1. Home
  2. Benchmarks
  3. Integration Bench
  4. task-0048
task-0048 · polling · writeback

Migrate the Brackett closure archive onto Paygrade

Vendor Paygrade Surface polling · writeback From Integrations / Workforce Systems, Northgate Facilities Group Mean score 64.7 Resolved by 11/17 211 graded checks

Results

The ticket

This is PROBLEM.md exactly as the agent received it. Vendor documentation and the starter repository ship inside the task environment and are not reproduced here.

Migrate the Brackett closure archive onto Paygrade

From: Integrations / Workforce Systems, Northgate Facilities Group Vendor: Paygrade Surface: polling · writeback Category: migrate · Track: python · Tier: 3

Context

Brackett HR is being retired at the end of the month. Its final closure archive is the last record of workers, placements, and pay periods that the branch closed. The overnight bridge will disappear with Brackett, leaving Paygrade as the system of record. The archive layout and the customer’s cutover rules are in docs/brackett-paygrade-cutover-note.md.

We need one register the operations desk can use on Monday: account for every archive row, apply the agreed worker closure where Paygrade still permits it, and identify anything the desk must resolve manually. Paygrade’s vendor documentation is in docs/ — start at docs/index.md.

What we need

The test harness runs your code exactly as follows — this command is the contract:

python -m pg_closure_migrate
# -> writes the output artifacts listed below

Read input/brackett_closure_archive.csv and give every row exactly one of:

  • already_closed — Paygrade has closed the record and the register carries its removal instant.
  • closed_here — Paygrade still holds a worker with no running placement; close that worker there.
  • blocked — Paygrade still holds a worker with a running placement; name the placements holding it open.
  • no_close_surface — Paygrade still holds a non-worker for which this task has no write surface.
  • not_in_paygrade — Paygrade has neither the record nor a published removal for that id.

A worker closed by this pass must have employment status terminated. The register must also include Paygrade removals absent from the archive under discovered. WORKER, PLACEMENT, and PERIOD map to Paygrade employee, assignment, and payrun respectively.

Output artifacts

  • output/result.json{"rows": [...], "counts": {...}, "discovered": [...]}. Each row carries ref, record_kind, pg_id, outcome, removed_at, and blocked_by; discovered entries carry entity, id, and deleted_at.
  • output/import_report.csv — header brackett_ref,record_kind,pg_id,outcome,removed_at,blocked_by, followed by one row per archive row. Use an empty field where a value does not apply and join placement ids in blocked_by with ;.
  • output/writeback_log.json — one entry per worker this pass closes: {"brackett_ref", "pg_id", "status"}.

Environment

VariableMeaning
VENDOR_BASE_URLVendor sandbox base URL (for example, http://paygrade:8000)
OUTPUT_DIRDirectory where output artifacts land (defaults to ./output)
PG_APP_TOKENVendor credential injected by the test harness

Engineering expectations

This ships to production, so the usual bar applies:

  • Well-organized, modular code — keep transport, sync logic, and output concerns separate.
  • Tests, runnable with pytest, covering the core logic you add or change.
  • Be a good API citizen: handle the vendor’s real-world behavior the way a production integration must, and don’t hammer endpoints in retry loops. Our platform team audits vendor request logs — sloppy conduct gets flagged even when the data lands correctly.

Done when

The entry command exits 0, every archive row has the right outcome, every permitted worker closure is applied, no other worker is changed, blocked rows identify their holders, and the register accounts for Paygrade removals absent from the archive.

Graded checks (211)

Names of every assertion the grader runs for this task. Per-attempt pass/fail and details are on each trajectory page.

  • pgclos_cutover_pass_completed
  • pgclos_result_covers_every_archive_row
  • pgclos_result_row_identity_and_schema_exact
  • pgclos_import_report_agrees_with_result
  • pgclos_import_report_exact
  • pgclos_outcome_counts_match
  • no_credentials_in_query_string
  • no_secrets_echoed_to_vendor
  • pgclos_outcome_BK-1001
  • pgclos_outcome_BK-1002
  • pgclos_outcome_BK-1003
  • pgclos_outcome_BK-1004
  • pgclos_outcome_BK-1005
  • pgclos_outcome_BK-1006
  • pgclos_outcome_BK-1007
  • pgclos_outcome_BK-1008
  • pgclos_outcome_BK-1009
  • pgclos_outcome_BK-1010
  • pgclos_outcome_BK-1011
  • pgclos_outcome_BK-1012
  • pgclos_outcome_BK-1013
  • pgclos_outcome_BK-1014
  • pgclos_outcome_BK-1015
  • pgclos_outcome_BK-1016
  • pgclos_outcome_BK-1017
  • pgclos_outcome_BK-1018
  • pgclos_outcome_BK-1019
  • pgclos_outcome_BK-1020
  • pgclos_outcome_BK-1021
  • pgclos_outcome_BK-1022
  • pgclos_outcome_BK-1023
  • pgclos_outcome_BK-1024
  • pgclos_outcome_BK-1025
  • pgclos_outcome_BK-1026
  • pgclos_outcome_BK-1027
  • pgclos_outcome_BK-1028
  • pgclos_outcome_BK-1029
  • pgclos_outcome_BK-1030
  • pgclos_outcome_BK-1031
  • pgclos_outcome_BK-1032
  • pgclos_outcome_BK-1033
  • pgclos_outcome_BK-1034
  • pgclos_outcome_BK-1035
  • pgclos_outcome_BK-1036
  • pgclos_outcome_BK-1037
  • pgclos_outcome_BK-1038
  • pgclos_outcome_BK-1039
  • pgclos_outcome_BK-1040
  • pgclos_outcome_BK-1041
  • pgclos_outcome_BK-1042
  • pgclos_outcome_BK-1043
  • pgclos_outcome_BK-1044
  • pgclos_outcome_BK-1045
  • pgclos_outcome_BK-1046
  • pgclos_outcome_BK-1047
  • pgclos_outcome_BK-1048
  • pgclos_outcome_BK-1049
  • pgclos_outcome_BK-1050
  • pgclos_outcome_BK-1051
  • pgclos_outcome_BK-1052
  • and 151 more