Noticed while implementing the analytics datasets (#9); filed rather than fixed because
src/views/ was outside that card's file surface.
Observation
src/views/task.view.ts, the late list view:
filter: [
{ field: 'due_date', operator: 'less_than', value: '{today}' },
{ field: 'status', operator: 'in', value: ['open', 'in_progress'] },
],
The product's definition of late (#9, and duly_duty.grace_days's own field description —
"Days after the due date before an open task counts as late") is:
due_date + grace_days is past, and the task is not done
The view drops the + grace_days. So a task whose duty grants 7 days of grace shows up in
"Late" the morning after its due date — six days before it is late. The view's own comment
explains why it reads stored columns rather than a flag, which is right; it just does not
mention that it is also dropping grace.
Consequence in use: grace is the mechanism that stops a monthly duty due on the 5th from
looking failed on the 6th, and the one screen a manager reads for lateness ignores it.
Every duty that sets a non-zero grace is mis-reported by exactly that many days.
This is the same root gap as the missing on-time measures
Not independently fixable today. A view filter is { field, operator, value } and there is
no operator that compares a column against another column plus an offset held in a third
column — the same limitation that removed tasks_done_on_time, tasks_late and the
on-time rate from duly_duty_health in #9. Filed upstream as
objectstack-ai/objectstack#14104.
So this is not "fix the view", it is "the app has two surfaces that both need the same
missing capability, and only one of them currently admits it". #9's dataset omits the
measure and says why; this view ships an approximation silently.
Suggested handling
Two options, both cheap, neither requiring the upstream fix:
- Say so in the view. Rename to something honest (
Past due) and/or add a comment
recording that grace is not applied and why. Costs nothing and stops the next reader
assuming the view is authoritative.
- Leave the filter, fix the framing. Keep
Late but treat #14104 as the blocker and
link it from the view so the two surfaces tell the same story.
Flagging it as a product decision rather than picking one: whether "Late" should mean
"past due" or "past grace" on the operational screen is a call for the maintainer, and it
may legitimately differ from what the metric layer counts.
Noticed while implementing the analytics datasets (#9); filed rather than fixed because
src/views/was outside that card's file surface.Observation
src/views/task.view.ts, thelatelist view:The product's definition of late (#9, and
duly_duty.grace_days's own field description —"Days after the due date before an open task counts as late") is:
The view drops the
+ grace_days. So a task whose duty grants 7 days of grace shows up in"Late" the morning after its due date — six days before it is late. The view's own comment
explains why it reads stored columns rather than a flag, which is right; it just does not
mention that it is also dropping grace.
Consequence in use: grace is the mechanism that stops a monthly duty due on the 5th from
looking failed on the 6th, and the one screen a manager reads for lateness ignores it.
Every duty that sets a non-zero grace is mis-reported by exactly that many days.
This is the same root gap as the missing on-time measures
Not independently fixable today. A view filter is
{ field, operator, value }and there isno operator that compares a column against another column plus an offset held in a third
column — the same limitation that removed
tasks_done_on_time,tasks_lateand theon-time rate from
duly_duty_healthin #9. Filed upstream asobjectstack-ai/objectstack#14104.
So this is not "fix the view", it is "the app has two surfaces that both need the same
missing capability, and only one of them currently admits it". #9's dataset omits the
measure and says why; this view ships an approximation silently.
Suggested handling
Two options, both cheap, neither requiring the upstream fix:
Past due) and/or add a commentrecording that grace is not applied and why. Costs nothing and stops the next reader
assuming the view is authoritative.
Latebut treat #14104 as the blocker andlink it from the view so the two surfaces tell the same story.
Flagging it as a product decision rather than picking one: whether "Late" should mean
"past due" or "past grace" on the operational screen is a call for the maintainer, and it
may legitimately differ from what the metric layer counts.