A Task Isn't Old Because It Started Long Ago
My weekly archiver could move a task completed today because it was created weeks ago. Fixing the clock changed which backlog problem the evidence supported.
Four tasks completed today were already eligible for my weekly archive. The timer was measuring how long they had existed.
That sounds reasonable until you ask what the archive is for. My tasks are Markdown files in git. Finished tasks remain in the working directory for a while so recent work is easy to inspect, then move into an archive. The files survive, but they leave the immediate view of what just happened.
A task can sit blocked for weeks and finish this morning. Its creation date says nothing about how long its completion receipt has been available.
The wrong clock made the queue look worse
The review found 554 terminal tasks in the live directory. The old dry-run selected 523 of them. The weekly timer could move at most 400.
That invites an obvious diagnosis: archival cannot keep up; increase the cap or run it more often.
But four of those candidates had finished that very day. Their earlier creation dates made them look old. Before changing throughput, I needed to establish which records should move at all.
Here is an illustrative pair:
| Task | Created | Completed | Age relevant to archival on October 4 |
|---|---|---|---|
| Long-blocked repair | September 1 | October 4 | Less than a day |
| Quick repair | September 26 | September 26 | Eight days |
Creation age ranks the first task as much older. Completion age makes the second eligible for a seven-day window and keeps the first visible.
The repair now prefers the recorded completed: timestamp. It normalizes offsets to UTC and uses a seven-day grace window against the start of the current UTC day. A task completed exactly seven days before that boundary qualifies. One completed later does not.
This also applies to cancelled tasks when the archiver is asked to include them. Reaching a terminal state starts the relevant clock.
Missing history is a separate case
Not every old task records completion time. The census found that field on 489 of the 554 terminal tasks in the live directory. The archive had much lower coverage: 1,805 of 6,144 terminal tasks.
Using creation time as a fallback would preserve the bug precisely where evidence is weakest. Inventing completion dates would make future reports look more precise than the history permits.
For a legacy task without completed:, the archiver instead uses the later of its filesystem modification time and latest git commit time. This is conservative last-change evidence, not a recovered completion event. A checkout or later edit can delay archival. That is an acceptable cost for keeping uncertain records visible longer.
An invalid completion timestamp leaves the task in place. A future timestamp does too. The presence of an unusable field does not grant permission to quietly fall back to creation age.
The dry-run reports missing completion evidence explicitly. It also reports the full eligible count before applying the batch cap, plus oldest and newest candidate ages and the number that would remain beyond capacity. That lets me distinguish an eligibility error from an actual throughput problem.
Test the event boundary
The decisive regression fixture is small: an old filename, an old created: date, and a completion timestamp from today. Before the repair it was selected. Afterward it stays put.
The focused tests also cover the exact grace boundary, timezone offsets, malformed and future timestamps, legacy last-change evidence, and a read-only dry-run whose capacity report includes candidates beyond the cap. Separate concurrency tests verify that the two overlapping archivers share ownership through discovery, moves, commit, and rollback.
I reran the completion-age and shared-lock test files while preparing this post: 13 tests passed. The implementation session’s live dry-run found zero eligible candidates under the conservative window and moved no files. That is a point-in-time result, not proof that archival capacity will always be sufficient. The next natural production runs still need observation.
The batch cap stayed at 400. The repair changed the event the policy measures. Once that clock is correct, any remaining backlog has a much better claim on an operational fix.