A guard, not a build. Removal was floated in the meeting and rejected -
Marlena tracks actual hours so they can be measured - and CLAUDE.md carries
that as a recorded decision. Verified after eight waves of change:
- Actual Hours exists in Closeout (wp_actual_hrs), persists through collect,
and prints on the export
- it is OPTIONAL: a package closes with it empty (driven, not assumed)
- it rolls up per T6.4: rollup_check has pinned actual-hours aggregation at
every level since wave 6, and /api/wps/metrics carries actual_hours in its
buckets
The follow-up the done-when requires is logged as BL-023: a productivity
factor (actual / estimated) - the rollup endpoints already carry both sums,
so it is a presentation task awaiting its own item id and a placement call.
Verification: export_check.py extended to 20/20 (the CR-017 section).
Items: CR-017
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>