The active-day metric in scripts/dogfooding/dogfood-snapshot.py unions dates from AuditLogs, Cards, AutomationProposals, ChatMessages and LlmRequests without applying noise_board_ids(). So on a shared dev database, a day on which only E2E fixtures or seeded demo boards were touched counts as an active dogfooding day.
That matters because active days is the metric #1271 is scored on, and the rubric in docs/dogfooding/README.md keys its archive/revive bands to it.
Why it was not fixed inline
The join is not uniformly available. Cards reach a board through Columns, but AuditLogs, ChatMessages and LlmRequests are not board-scoped at all — there is no honest way to attribute a chat message or an LLM request to a demo board without inventing an attribution rule. Filtering only the tables that can be filtered would produce a number that is neither all-activity nor real-activity, which is worse than the current one because it would look precise.
Current mitigation
The tool already warns loudly when more than half the boards are fixtures, and both docs make a separate TASKDECK_DOGFOOD_DB the first structural step — which dissolves the problem rather than approximating around it. On a clean dogfooding database there is no fixture activity to exclude.
So this is a real defect only for the shared-dev-database case, which is explicitly the case the docs tell you not to measure.
Suggested fix, when it is worth doing
Either:
- Attribute what can be attributed (
Cards via Columns.BoardId, AutomationProposals.BoardId) and report two numbers — all activity and board-attributable-non-fixture activity — never a single blended one; or
- Add a
--exclude-fixtures flag that drops the non-attributable tables entirely and says so in the output, so the reader knows the count is a lower bound.
Option 2 is probably the honest one: a smaller number that is provably real beats a larger one that is partly fixture.
Provenance
Codex P1 on PR #1478. Fixed alongside it: the funnel now counts applies by AppliedAt (a status-based count understated it 17x), LlmRequests added as an activity source, the verdict scores the window rather than all time, and a degenerate DB no longer reports "not started".
The active-day metric in
scripts/dogfooding/dogfood-snapshot.pyunions dates fromAuditLogs,Cards,AutomationProposals,ChatMessagesandLlmRequestswithout applyingnoise_board_ids(). So on a shared dev database, a day on which only E2E fixtures or seeded demo boards were touched counts as an active dogfooding day.That matters because active days is the metric
#1271is scored on, and the rubric indocs/dogfooding/README.mdkeys its archive/revive bands to it.Why it was not fixed inline
The join is not uniformly available.
Cardsreach a board throughColumns, butAuditLogs,ChatMessagesandLlmRequestsare not board-scoped at all — there is no honest way to attribute a chat message or an LLM request to a demo board without inventing an attribution rule. Filtering only the tables that can be filtered would produce a number that is neither all-activity nor real-activity, which is worse than the current one because it would look precise.Current mitigation
The tool already warns loudly when more than half the boards are fixtures, and both docs make a separate
TASKDECK_DOGFOOD_DBthe first structural step — which dissolves the problem rather than approximating around it. On a clean dogfooding database there is no fixture activity to exclude.So this is a real defect only for the shared-dev-database case, which is explicitly the case the docs tell you not to measure.
Suggested fix, when it is worth doing
Either:
CardsviaColumns.BoardId,AutomationProposals.BoardId) and report two numbers — all activity and board-attributable-non-fixture activity — never a single blended one; or--exclude-fixturesflag that drops the non-attributable tables entirely and says so in the output, so the reader knows the count is a lower bound.Option 2 is probably the honest one: a smaller number that is provably real beats a larger one that is partly fixture.
Provenance
Codex P1 on PR #1478. Fixed alongside it: the funnel now counts applies by
AppliedAt(a status-based count understated it 17x),LlmRequestsadded as an activity source, the verdict scores the window rather than all time, and a degenerate DB no longer reports "not started".