Nightly roster census disagrees with CrewCall about who works here
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.
Nightly roster census disagrees with CrewCall about who works here
From: Integrations / Workforce Analytics Vendor: CrewCall Surface: polling Category: fix · Track: python · Tier: 3
Context
Fenmarsh Care Group runs its staffing off CrewCall. Every night at 02:00 our census job takes a snapshot of the roster and hands the capacity model a line per crew member plus two breakdowns — one per role, one per status. The model books agency cover off those breakdowns, so a number being out by three costs real money in either direction.
The job runs clean every night and has done for a year. Three things came in over the last fortnight and nobody has connected them yet:
“The model has been ordering agency drivers all month and we have drivers sitting at home. It thinks we are short and we are not.”
“Priya shows up twice in the morning export, same worker id on both lines. Payroll noticed, we didn’t.”
“Two of the night carers came up as leavers on Tuesday and were back on Wednesday. Neither of them has been near a resignation form.”
The headline is not the problem: Ops cross-check the total against payroll every Friday and it has matched every week since the job went in.
Full vendor documentation is in docs/ — start at docs/index.md.
What we need
The census fixed, so the model can be trusted. Two rules the analytics desk works to, which are ours and not CrewCall’s:
- The census is one line per crew member the tenant holds, and every crew
member the tenant holds gets one. A carer CrewCall has taken off the books is
still one of the tenant’s records: they are carried as
removed, kept out of the active headcount and out of the per-status breakdown, and still counted in their role’sremovedcolumn. - The headline totals and the two breakdowns describe the same set of crew members as the census file itself, and that set is what CrewCall actually holds for us.
The test harness runs your code exactly as follows — this command is the contract:
python -m fenmarsh_census
Output artifacts
output/roster_census.csv— one line per crew member, sorted byworker_id, columnsworker_id,role,status,standing.standingisactiveorremoved.output/census_summary.json—roster_rows,active_headcount,removed_headcount,pages_read, plusby_role(one entry per role, withactiveandremoved) andby_status(one entry per status, withheadcount).
Environment
| Variable | Meaning |
|---|---|
VENDOR_BASE_URL | Vendor sandbox base URL (e.g. http://vendor:8000) |
CC_API_KEY | Vendor credential injected by the test harness |
OUTPUT_DIR | Directory where output artifacts land (defaults to ./output) |
PAGE_LIMIT | Page size the roster sweep asks for |
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 run exits 0, both artifacts are written, and the census describes exactly the crew members CrewCall holds for us — each of them once.
Graded checks (67)
Names of every assertion the grader runs for this task. Per-attempt pass/fail and details are on each trajectory page.
- census_run_completed
- census_roster_row_total_matches_the_tenant
- census_active_headcount_matches_the_tenant
- census_removed_headcount_matches_the_tenant
- census_totals_describe_the_lines_it_wrote
- census_counts_no_carer_twice
- census_artifact_exact
- census_summary_artifact_exact
- census_covers_every_carer_the_tenant_holds
- census_role_barista_split_exact
- census_role_cashier_split_exact
- census_role_cleaner_split_exact
- census_role_dishwasher_split_exact
- census_role_driver_split_exact
- census_role_host_split_exact
- census_role_line_cook_split_exact
- census_role_server_split_exact
- census_role_stocker_split_exact
- census_role_warehouse_split_exact
- census_status_available_headcount_exact
- census_status_inactive_headcount_exact
- census_status_off_shift_headcount_exact
- census_status_on_shift_headcount_exact
- census_line_wkr_0001_exact
- census_line_wkr_0010_exact
- census_line_wkr_0012_exact
- census_line_wkr_0019_exact
- census_line_wkr_0023_exact
- census_line_wkr_0028_exact
- census_line_wkr_0034_exact
- census_line_wkr_0036_exact
- census_line_wkr_0038_exact
- census_line_wkr_0046_exact
- census_line_wkr_0047_exact
- census_line_wkr_0053_exact
- census_line_wkr_0057_exact
- census_line_wkr_0059_exact
- census_line_wkr_0066_exact
- census_line_wkr_0067_exact
- census_line_wkr_0071_exact
- census_line_wkr_0076_exact
- census_line_wkr_0080_exact
- census_line_wkr_0083_exact
- census_line_wkr_0084_exact
- census_line_wkr_0087_exact
- census_line_wkr_0094_exact
- census_line_wkr_0096_exact
- census_line_wkr_0097_exact
- census_line_wkr_0102_exact
- census_line_wkr_0106_exact
- census_line_wkr_0108_exact
- census_line_wkr_0110_exact
- census_line_wkr_0115_exact
- census_line_wkr_0118_exact
- census_line_wkr_0120_exact
- census_line_wkr_0190_exact
- census_line_wkr_0194_exact
- roster_sweep_reran_from_the_first_window
- roster_sweep_spanned_every_position_the_tenant_holds
- rerun_completed
- and 7 more