Build the nightly payroll bridge for the punch export
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.
Build the nightly payroll bridge for the punch export
From: Payroll Systems / Harbor Point Facilities Vendor: Rosterly Surface: polling, writeback Category: build · Tier: 3
Context
Our overnight rota lives in Rosterly. Every morning the timekeeping partner drops a file of clock-in/clock-out pairs keyed by Rosterly shift.
Payroll pays by the day, so a punch crossing midnight must be split and each day given its minutes. The repository contains the initial bridge.
Payroll Systems’ own runbook for the job is at
docs/harborpoint-payroll-runbook.md. Full vendor documentation is in docs/ —
start at docs/index.md.
The rules payroll work to
These are ours, not Rosterly’s.
- A payroll day is a calendar day at the shift’s venue. Split a punch at venue midnight; its daily minutes must add up to its total length.
- The partner corrects punches by re-sending them. A correction carries the
same
punch_ref. The last row the file gives for apunch_refis the punch; earlier rows for that ref are what the clock held before a supervisor fixed it, and they are not additional work. - A punch we cannot place is an exception, not a guess. If Rosterly has no
such shift, the reason is
unknown_shift; if Rosterly has it but no longer holds it against the rota, the reason isdeleted_shift. Exceptions stay off the payroll report entirely and nothing is written back for them. - Arrival is the clock-on measured against the shift’s scheduled start:
earlyat 5 minutes or more before it,lateat 5 minutes or more after it,on_timein between. - Scheduling get told about split punches. Each gets one note against the crew member, using the package’s established key and format and carrying the punch, shift, venue timezone, and daily minutes. The bridge is routinely re-run over the same export.
What we need
The harness runs your code exactly as follows — this command is the contract:
python -m harborpoint_bridge
# -> writes the output artifacts listed below
The export is at input/punches.csv: punch_ref, shift_id, punch_in_utc,
punch_out_utc.
Output artifacts
output/import_report.csv— header row plus one row per payroll day of every payable punch:punch_ref,shift_id,worker_id,venue_timezone,payroll_date(YYYY-MM-DD),minutes.output/result.json—punch_count,bridged_count,unbridgeable_count,split_line_count,midnight_split_count,total_minutes,notes_posted, pluspunches(one entry per payable punch:punch_ref,shift_id,worker_id,venue_timezone,arrival,minutes, anddays, a list ofpayroll_date/minutes) andunbridgeable(punch_ref,shift_id,reason).output/writeback_log.json—notes: one entry per note the run wrote back, each withpunch_ref,shift_id,worker_id,idempotency_key,note_id.
Environment
| Variable | Meaning |
|---|---|
VENDOR_BASE_URL | Vendor sandbox base URL (e.g. http://vendor:8000) |
RY_CLIENT_ID | Vendor credential injected by the test harness |
RY_CLIENT_SECRET | Vendor credential injected by the test harness |
INPUT_FILE | Path to the partner’s punch export |
OUTPUT_DIR | Directory where output artifacts land (defaults to ./output) |
PAGE_LIMIT | Optional batch-size override |
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 payable punch’s minutes sit on the payroll days the venue worked them, every punch we cannot place is on the exception list with a reason and nowhere else, scheduling holds exactly one note per split punch, and running the bridge again over the same export changes neither the artifacts nor what Rosterly holds.
Graded checks (93)
Names of every assertion the grader runs for this task. Per-attempt pass/fail and details are on each trajectory page.
- payroll_bridge_run_completed
- payroll_headline_counts_exact
- result_json_contract_exact
- import_report_contract_exact
- punch_pch_0101_payroll_split_exact
- punch_pch_0102_payroll_split_exact
- punch_pch_0103_payroll_split_exact
- punch_pch_0104_payroll_split_exact
- punch_pch_0105_payroll_split_exact
- punch_pch_0106_payroll_split_exact
- punch_pch_0107_payroll_split_exact
- punch_pch_0108_payroll_split_exact
- punch_pch_0109_payroll_split_exact
- punch_pch_0110_payroll_split_exact
- punch_pch_0111_payroll_split_exact
- punch_pch_0112_payroll_split_exact
- punch_pch_0113_payroll_split_exact
- punch_pch_0114_payroll_split_exact
- punch_pch_0115_payroll_split_exact
- punch_pch_0116_payroll_split_exact
- punch_pch_0117_payroll_split_exact
- punch_pch_0118_payroll_split_exact
- punch_pch_0119_payroll_split_exact
- punch_pch_0120_payroll_split_exact
- punch_pch_0121_payroll_split_exact
- punch_pch_0122_payroll_split_exact
- punch_pch_0123_payroll_split_exact
- punch_pch_0124_payroll_split_exact
- punch_pch_0200_payroll_split_exact
- punch_pch_0201_payroll_split_exact
- punch_pch_0202_payroll_split_exact
- punch_pch_0210_payroll_split_exact
- punch_pch_0211_payroll_split_exact
- report_pch_0101_lines_exact
- report_pch_0102_lines_exact
- report_pch_0103_lines_exact
- report_pch_0104_lines_exact
- report_pch_0105_lines_exact
- report_pch_0106_lines_exact
- report_pch_0107_lines_exact
- report_pch_0108_lines_exact
- report_pch_0109_lines_exact
- report_pch_0110_lines_exact
- report_pch_0111_lines_exact
- report_pch_0112_lines_exact
- report_pch_0113_lines_exact
- report_pch_0114_lines_exact
- report_pch_0115_lines_exact
- report_pch_0116_lines_exact
- report_pch_0117_lines_exact
- report_pch_0118_lines_exact
- report_pch_0119_lines_exact
- report_pch_0120_lines_exact
- report_pch_0121_lines_exact
- report_pch_0122_lines_exact
- report_pch_0123_lines_exact
- report_pch_0124_lines_exact
- report_pch_0200_lines_exact
- report_pch_0201_lines_exact
- report_pch_0202_lines_exact
- and 33 more