Skip to content
maksim zaytsev
Writing

Sep 2, 2026 · 6 min

Logging a workday from git evidence

Time tracking is the kind of chore that gets done at six in the evening from memory, badly. The evidence of what I actually did is already there — commits, pull requests, calendar events — so I wrote an agent skill that reads it and files the day into 7pace Timetracker, the tool our Azure DevOps organisation uses. Here is the shape of it and the rules that made it trustworthy.

The pipeline

  1. Gather evidence. Commits and pull requests for the day from Azure DevOps (through the az CLI, because its --query returns only the fields you ask for), meetings from a published calendar feed.
  2. Build the plan. Meetings sit at their calendar times; work blocks fill the gaps and get mapped to the work items behind the commits. Half-hour granularity, a typical day of eight to nine hours, one activity type per block.
  3. Show it as a table. Time range, work item, hours, activity, comment.
  4. Wait for an explicit “go”. Nothing is written until I say so, and corrections loop back to step 2.
  5. Write and verify. Entries go through the 7pace MCP server or, if it's missing on a machine, through a zero-dependency Node script that makes the same calls.

The hard rules

The skill file states a handful of rules in plain language, and they do more work than any amount of code:

  • Worklogs of one day must never overlap. Entries go strictly one after another.
  • Never write without approval.
  • Never log into the future. On the current day, no block may end after “now”.
  • Internal meetings have no work item. Mission meetings go on that mission's epic.
  • Never print or commit the token.

The overlap rule is also enforced by the script, which refuses an overlapping plan outright. A rule the model reads and a check the code performs are not redundant: the first prevents most mistakes, the second catches the rest.

What the tool had to learn

The upstream MCP server couldn't log a single entry against our instance. Activity types came back in a shape it didn't parse, so it sent worklogs without one and the API rejected them; a heuristic turned 15-minute entries into 15-hour ones; the list endpoint ignored its date filters. I forked it and fixed those, then added the two things the pipeline actually needed: an optional start time, so entries can be laid out sequentially, and an optional work item, because meetings don't have one. The no-overlap rule went into the tool's description — the place the model reads before calling it.

What I'd tell someone building the same thing

  • Put the rules where the model will see them at decision time: the tool description and the skill, not a README.
  • Make the tool fail loudly. An unknown activity type should list the valid ones, not silently drop the field and let the API answer with a cryptic 400.
  • Keep an approval gate on every write. Reading evidence is free; writing worklogs is not.
  • Keep secrets out of the repo: .env.example in, .env ignored, and a check in the script that refuses to run with a placeholder token.

The result is a few minutes a day instead of a reconstructed guess, and a log that matches what the repository says happened.