The Timesheet Check Build Standard
How every hour on the payroll comes to trace to a person, a day and a job, with the odd ones looked at by somebody and nothing paid that a person did not release. Written so you can build it yourself.
Used by
- Payroll Officer
- Office Manager
- Construction Administrator
- Bookkeeper
11 min read · Published by AI Pathway
Using Claude? This standard installs as a skill. Guides for ServiceM8, Xero and Simpro.
How to get this live in your business
Build it for mePick a time and we scope the check against your roster, your job system and your payroll.What this is
An open build standard for the check between the hours people capture and the payroll run, for a trades, construction or services business with a roster and a job system.
The core rule
Totals derive from entries. A penalty applied names the rule edition it came from. An anomaly leaves the queue only with a person's name and a reason. Nothing reaches payroll without a release.
What it does not do
It does not decide which award clause applies to an odd shift, does not clear an anomaly on its own, and does not put anything into payroll that a named person did not release.
The hard part
Not the arithmetic. The award edition that moved between periods, and the export that ran twice because nobody read back whether it already had.
The sheet said forty hours. The site app said forty-three and a half, two of them on a job the person was never on, and Saturday was paid at the weekday rate because the spreadsheet formula was written before the award changed. Nobody did anything wrong on purpose. The check that would have caught all three did not exist, so the payroll run was the check.
One period, entries to payroll
- The period closes.
- Every entry is traced to a person, a day and a job that person was allocated. An entry that does not trace is an anomaly, not a line.
- Daily and weekly totals are computed from entries, never typed. Overlaps, over-hours days, missing breaks and unrostered days join the anomaly queue with an owner each.
- Every penalty or allowance applied cites a rule with an edition and an effective date. An entry the dated rule does not plainly cover is parked for a person.
- Are the anomalies at zero, each resolved by a person with a reason, and has a named person released the period? If no, the period waits with the queue in front of its owners, and the run still publishes hours, anomalies found and resolved, and that nobody has released.
- If yes, one export is written into payroll with its id back.
- Has the period stayed unchanged since the export? If yes, the run publishes hours, anomalies found and resolved, and the release. If no, the export is updated, never duplicated.
Take the spec to Claude, ChatGPT or Copilot. The sentence to paste is one click away.
1. What this standard covers
Any business where hours are captured somewhere other than the payroll system: a site app, a kiosk, a paper sheet, the job system itself. Trades, construction, cleaning, labour hire, anything with a roster and jobs. If a person’s pay depends on entries somebody else made, this applies.
It covers the check, not the pay. Interpreting which award clause applies to an unusual shift is a question for a person with a cited rule in front of them, and the shape of that question is the Cited Answer standard. This standard reads a dated rule, cites it, and parks what it does not plainly cover. The timesheet paper is the argument beside it.
The failure this prevents is specific. Not the wrong number on one sheet. The period that reached payroll with an anomaly nobody looked at, a penalty from an edition that had lapsed, and no name on the release.
2. The closed list of anomalies
Six kinds. A closed list, so an anomaly always has a name and an owner, and a new kind is a change to the standard rather than a note somebody typed.
| Kind | What it is | Who owns it |
|---|---|---|
| over_hours | More hours in a day than the business's own limit | The person's supervisor |
| overlap | Two entries for one person that share a minute | The person's supervisor |
| missing_break | A long entry with no break recorded | The person's supervisor |
| not_rostered | An entry on a day the roster did not have them working | Whoever keeps the roster |
| not_allocated | An entry on a job the person was never allocated to | The job's owner |
| rule_unclear | A situation the dated rule does not plainly cover | Whoever answers for the award |
An entry with an open anomaly is not a line on the sheet. It is not paid at a guessed figure and it is not quietly dropped. It waits, in front of its owner, with a reason.
3. The objects, and what is in them
Seven objects. The card and the release are the two most timesheet tools leave out, because a total that adds up looks finished.
For your developer. Show the fields
Entry # captured on site, in the app, on paper
- id, person_id, date, job_id (null if none was given)
- start, end, break_minutes, source (site | app | paper)
- flags[] (what the capture app noticed: a disputed break, an odd shift)
Allocation # theirs, from the job system
- person_id, job_id, date
Roster
- person_id, date, rostered
Rule # the award, as a dated instrument
- id, instrument, edition, effective_from, effective_to
- text, covers[] (the situations this edition plainly names)
Anomaly
- id, entry_id, kind (from the closed list), owner (a person)
- decision { by, reason, at } (a person's), resolution { by, reason, at }
- evidence[]
Card # one per rule applied to an entry
- entry_id, rule_id, edition, effective_from
Period
- id, from, to
- released_by (a person; null until they do)
- export_external_id (payroll's own id; null means the export failed)A Period with an export_external_id and no released_by is the defect this standard exists to make unrepresentable. An Anomaly with a resolution and no decision by a person is the other, and neither should be writable.
4. The checks, in order
The order is the claim. The entry is traced before it is totalled, the rule is read before a card is written, and the anomalies are at zero before the release is even asked for.
- Every entry traces to a person, a day and a job. Every entry carries a person id from the contact list, a date, and a job id from the job system that the person was allocated on that day. An entry with no job, or a job the person was not allocated, is an anomaly and never a line on the sheet.
- Daily and weekly totals are computed from entries, never typed. A total is the sum of the entries it names, computed at run time. A total that names no entries, or whose hours differ from the sum of the entries it names, is a typed total and fails.
- An anomaly is one of a closed list of kinds, and it has an owner. Over-hours in a day, overlapping entries, a missing break, an entry on a day not rostered, a job not allocated, and a rule that does not plainly apply. Each anomaly carries a kind from that list and the name of the person who owns it. A kind outside the list, or an anomaly with no owner, fails.
- Any penalty, overtime or allowance applied cites the rule, its edition and its effective date. An entry that attracts overtime, a weekend penalty or an allowance carries a card naming the rule, its edition and the date it took effect, read from the rule store at run time. A rule applied with no card fails.
- A retired rule edition cannot apply to the next period. Once a rule edition is retired, the next period applies the edition in force for its dates or parks the entry. A card for a period after the retirement that cites the retired edition fails.
- An entry the dated rule does not plainly cover is parked for a person. A disputed break, an unusual shift, a situation the rule text does not plainly name: the entry is parked with kind rule_unclear and an owner, and no card is written for it. The build never decides which clause applies.
- An anomaly leaves the queue only with a person's name and a reason. A resolution is a person's name, a reason from the list approved, corrected or rejected, and the time. The person's decision is attached as evidence. An anomaly resolved with no name, or with no decision behind it, fails.
- Nothing reaches payroll without a release by a named person. The period export is written only after a named person releases the period, and only when every anomaly in it is resolved. A run with no release writes nothing. An export with no release behind it, or with an open anomaly, fails.
- One export per period, written once, updated on a second release. The export is keyed to the period. A second release for the same period updates the existing export or refuses; it never writes a second one. A null external id is a failed export, not a success.
- Every period publishes hours, anomalies found and resolved, and the release, including a clean one. Each run publishes a report for the period: the hours by person and day, how many anomalies were found and how many resolved, and who released it or that nobody has. A clean period publishes too, so silence never means clean.
- Entries, anomalies, resolutions, rules cited and the release are retrievable by person and period. When a person disputes their pay, the record for that person and period shows every entry, every anomaly with who resolved it and why, every rule card, and who released the period.
- It survives the builder. Someone other than the builder can explain what it does, and it runs on an account the business owns.
- The pass test passes. On a real period with real entries: one overlapping pair caught, one unallocated job caught, one rule edition change parking the next period, one release by a person, and one export in the payroll system with its id.
5. The award is a rule you read, not one you interpret
Overtime after eight hours, a Saturday penalty, a meal allowance: each is a clause in an instrument with an edition and an effective date. The check applies one only when the entry plainly matches a situation that edition names, and when it does, the line carries a card saying which rule, which edition, from when. When the edition changes, the next period cites the new one, and the old one cannot produce a card.
An entry the rule does not plainly cover, a disputed break, a split shift nobody has seen before, is parked with the kind rule_unclear and an owner. The machine does not decide which clause applies. That is the one decision on this page that can end up in front of a tribunal, and it stays with a person who has the clause in front of them.
6. What stays with a person
- Every anomaly resolution, with their name and a reason: approved, corrected, or rejected.
- The release of the period to payroll.
- Which award applies to the business, and which clause applies to the odd shift.
- Any dispute with the person whose hours they are. The check shows the entry; a person has the conversation.
The parts that move
Checked as at 26 September 2026
Modern award rates, penalties and allowances change on a schedule set by the Fair Work Commission, usually from the first full pay period on or after 1 July, and sometimes between. Hold each edition as a dated rule with an effective date, and let the period decide which edition applies. A formula copied into a spreadsheet in 2024 does not know that.
Check these against the primary instrument before you rely on them, and store the date you checked beside the value rather than hard-coding it. This standard tells you the shape and where to look. It is not legal advice and it does not tell you that anything complies.
8. Provider: what to stub, and what not to hand-roll
One step not to hand-roll: the release gate and the idempotent export into payroll, with an id back. Everything else a coding agent builds against the stub in an afternoon.
For your developer. Show the provider config
provider:
stub: local.mock_roster
production: none # no hosted step; runs on your own systems
stays local # yours, and the standard
- the trace against the roster and the allocations
- the totals, the anomaly queue, the cards
- the rule store with its editions and dates
the live step
- the release by a named person, then one export per period into
the payroll system with its id back. Runs on your own systems;
there is no hosted product for it.A vendor selling timesheet automation is usually selling the capture and the arithmetic, and is silent about who released the last period and which award edition the Saturday rate came from. Ask them those two first.
The pass test. On a real period, with the entries people actually captured. Seed two entries for one person that overlap: both must be in the anomaly queue with a supervisor’s name. Seed an entry on a job the person was never allocated: it must be an anomaly, not a line. Retire the current award edition and load the next with a later effective date: the following period must cite the new edition only, and an entry the new edition does not plainly cover must park with the kind rule_unclear. Clear every anomaly as a named person with a reason, release the period as a named person, and run twice an hour apart: exactly one export must exist in payroll with its own id, and the record for any person must show their entries, their anomalies with resolutions, the cards, and the release with a name. If the export exists without a release, or a card cites the retired edition, the standard is not implemented.
9. Conformance checklist
Hold a DIY build or a vendor to this. If a box is empty, it is not in production.
- 1. Every entry traces to a person, a day and a job. Every entry carries a person id from the contact list, a date, and a job id from the job system that the person was allocated on that day. An entry with no job, or a job the person was not allocated, is an anomaly and never a line on the sheet.
- 2. Daily and weekly totals are computed from entries, never typed. A total is the sum of the entries it names, computed at run time. A total that names no entries, or whose hours differ from the sum of the entries it names, is a typed total and fails.
- 3. An anomaly is one of a closed list of kinds, and it has an owner. Over-hours in a day, overlapping entries, a missing break, an entry on a day not rostered, a job not allocated, and a rule that does not plainly apply. Each anomaly carries a kind from that list and the name of the person who owns it. A kind outside the list, or an anomaly with no owner, fails.
- 4. Any penalty, overtime or allowance applied cites the rule, its edition and its effective date. An entry that attracts overtime, a weekend penalty or an allowance carries a card naming the rule, its edition and the date it took effect, read from the rule store at run time. A rule applied with no card fails.
- 5. A retired rule edition cannot apply to the next period. Once a rule edition is retired, the next period applies the edition in force for its dates or parks the entry. A card for a period after the retirement that cites the retired edition fails.
- 6. An entry the dated rule does not plainly cover is parked for a person. A disputed break, an unusual shift, a situation the rule text does not plainly name: the entry is parked with kind rule_unclear and an owner, and no card is written for it. The build never decides which clause applies.
- 7. An anomaly leaves the queue only with a person's name and a reason. A resolution is a person's name, a reason from the list approved, corrected or rejected, and the time. The person's decision is attached as evidence. An anomaly resolved with no name, or with no decision behind it, fails.
- 8. Nothing reaches payroll without a release by a named person. The period export is written only after a named person releases the period, and only when every anomaly in it is resolved. A run with no release writes nothing. An export with no release behind it, or with an open anomaly, fails.
- 9. One export per period, written once, updated on a second release. The export is keyed to the period. A second release for the same period updates the existing export or refuses; it never writes a second one. A null external id is a failed export, not a success.
- 10. Every period publishes hours, anomalies found and resolved, and the release, including a clean one. Each run publishes a report for the period: the hours by person and day, how many anomalies were found and how many resolved, and who released it or that nobody has. A clean period publishes too, so silence never means clean.
- 11. Entries, anomalies, resolutions, rules cited and the release are retrievable by person and period. When a person disputes their pay, the record for that person and period shows every entry, every anomaly with who resolved it and why, every rule card, and who released the period.
- 12. It survives the builder. Someone other than the builder can explain what it does, and it runs on an account the business owns.
- 13. The pass test passes. On a real period with real entries: one overlapping pair caught, one unallocated job caught, one rule edition change parking the next period, one release by a person, and one export in the payroll system with its id.
- 1
Hold the build to the checklist
The checks in this standard are what a working build looks like. Implement it yourself, hand it to a developer, or hand the page to an AI with the button below.
- 2
Do not hand-roll
There is no product for this step. Highest option: none. Checklist plus a build.
- 3
If you are stuck
Exceptions, three systems, a team that will not maintain a Zap, or an owner who wants it done. We implement when it has to survive the business.
Related reading
Want the whole thing by email?
This paper, plus the rest of the library. One click to stop them.