Skip to content

feat(features): extend FeatureDataLoader to join product.launch_date / discontinue_date for lifecycle E2E #116

@w7-mgfcode

Description

@w7-mgfcode

Context

PRP-3.1B landed _compute_lifecycle_features() and unit-tested it, but at the HTTP boundary POST /featuresets/compute emits zero lifecycle columns because FeatureDataLoader.load_sales_data() only returns sales columns — never joins product.launch_date / product.discontinue_date. The compute method silently skips when both source columns are absent (app/features/featuresets/service.py:489).

PRP-3.1E (#115 closes #109) ships the E2E integration test against the wired-up parts (replenishment + promotion) and explicitly omits lifecycle columns from PHASE2_EXPECTED_COLUMNS, with a docstring + PHASE doc note pointing at this gap.

Goal

Extend FeatureDataLoader so compute_features_for_series() joins product attrs onto the sales frame before calling service.compute_features(). After the change:

  • days_since_launch_lag1 and days_since_discontinue_lag1 should appear in the response when lifecycle_config is set.
  • TestPhase2EndToEnd::test_phase2_columns_appear should be extended to expect them (or a new test added).
  • The PHASE-3 doc note ("at the HTTP boundary, the current FeatureDataLoader does not yet join …") should be removed.

Acceptance

  • FeatureDataLoader.load_product_attrs(db, product_ids) (or equivalent) added with SQL-side filter on product.id.
  • compute_features_for_series() calls it when config.lifecycle_config is not None and merges onto df before constructing the service.
  • test_phase2_integration.py::PHASE2_EXPECTED_COLUMNS expanded to include the lifecycle columns.
  • PHASE-3 doc note removed.
  • All existing leakage / unit tests stay green.

Out of scope

  • Changing the lifecycle compute method itself (PRP-3.1B is the source of truth).
  • Plumbing promotion rows through FeatureDataLoader (separate follow-up — _promotion_rows_df defaults to empty at the HTTP boundary too, but promotion columns DO appear because the compute method emits them with all-zero values).

Refs

  • PRP-3.1E §16 Open Question 2
  • app/features/featuresets/service.py:489 (silent-skip condition)
  • app/features/featuresets/tests/test_phase2_integration.py (module docstring)
  • docs/PHASE/3-FEATURE_ENGINEERING.md ("Phase 2 Features (Retail-Depth)" section, lifecycle note)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions