Found while implementing #7036. Observation-class, filed unassigned: nothing a user hits today reports a wrong answer, but the fields are inert in a way that reads as working.
What is there
examples/app-todo/src/objects/task.object.ts:
is_completed: Field.boolean({ label: 'Is Completed', defaultValue: false, readonly: true }),
is_overdue: Field.boolean({ label: 'Is Overdue', defaultValue: false, readonly: true }),
Both are readonly, so a non-system caller's write to either is stripped on both write paths. Nothing else in the app writes them: no hook leg, no flow node, no action handler, and the seed data sets neither. They are therefore false on every row for the life of the app.
is_overdue additionally has a reader: the afterUpdate leg of src/objects/task.hook.ts logs when a task "became overdue", gated on data.is_overdue && previous && !previous.is_overdue. That condition can never be true, so the branch is unreachable. (#7036 repairs how that leg reads its record but does not change this.)
is_completed is the one with a visible partner: after #7036 the app maintains completed_date on the completion transition, so a reader comparing the two now sees a task with a completion date and is_completed: false.
Why it is a finding rather than a defect
No user-facing surface currently branches on either flag — no view filter, dashboard, report or dataset in the app reads them (is_overdue's only reader is the log line above). So nothing produces a wrong answer today; the cost is that a shipped reference app declares two derived flags and derives neither, which is the pattern an AI author copies.
Shape of the fix, if it is wanted
Three readings, and the choice is an app-semantics call rather than an obvious repair:
- Maintain them —
is_completed in the same beforeUpdate leg that stamps completed_date (they are the same transition); is_overdue needs a clock, so it belongs to a scheduled flow rather than a record hook.
- Derive them — make both formula fields, so they cannot drift from
status/due_date and are visible to list views without anything writing them.
- Remove them — if the example does not mean to demonstrate derived flags,
status and due_date already carry the information.
Found while implementing #7036. Observation-class, filed unassigned: nothing a user hits today reports a wrong answer, but the fields are inert in a way that reads as working.
What is there
examples/app-todo/src/objects/task.object.ts:Both are
readonly, so a non-system caller's write to either is stripped on both write paths. Nothing else in the app writes them: no hook leg, no flow node, no action handler, and the seed data sets neither. They are thereforefalseon every row for the life of the app.is_overdueadditionally has a reader: theafterUpdateleg ofsrc/objects/task.hook.tslogs when a task "became overdue", gated ondata.is_overdue && previous && !previous.is_overdue. That condition can never be true, so the branch is unreachable. (#7036 repairs how that leg reads its record but does not change this.)is_completedis the one with a visible partner: after #7036 the app maintainscompleted_dateon the completion transition, so a reader comparing the two now sees a task with a completion date andis_completed: false.Why it is a finding rather than a defect
No user-facing surface currently branches on either flag — no view filter, dashboard, report or dataset in the app reads them (
is_overdue's only reader is the log line above). So nothing produces a wrong answer today; the cost is that a shipped reference app declares two derived flags and derives neither, which is the pattern an AI author copies.Shape of the fix, if it is wanted
Three readings, and the choice is an app-semantics call rather than an obvious repair:
is_completedin the samebeforeUpdateleg that stampscompleted_date(they are the same transition);is_overdueneeds a clock, so it belongs to a scheduled flow rather than a record hook.status/due_dateand are visible to list views without anything writing them.statusanddue_datealready carry the information.