From b1002eef61f9f5ea3a3c7e72a942801c1f021368 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 11 Feb 2026 19:51:32 +0000 Subject: [PATCH 1/4] Initial plan From 455bf341be8e341726ca31fc023509f11e521b21 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 11 Feb 2026 19:54:45 +0000 Subject: [PATCH 2/4] Apply code improvements: fix coordinate masking comment and replace magic number weights with documented constant Co-authored-by: bartzbeielstein <32470350+bartzbeielstein@users.noreply.github.com> --- ...fe_n_to_1_with_covariates_and_dataframe.py | 44 ++++++++++++++++--- 1 file changed, 37 insertions(+), 7 deletions(-) diff --git a/src/spotforecast2_safe/tasks/task_safe_n_to_1_with_covariates_and_dataframe.py b/src/spotforecast2_safe/tasks/task_safe_n_to_1_with_covariates_and_dataframe.py index 3821b4e2f..e3a94944d 100644 --- a/src/spotforecast2_safe/tasks/task_safe_n_to_1_with_covariates_and_dataframe.py +++ b/src/spotforecast2_safe/tasks/task_safe_n_to_1_with_covariates_and_dataframe.py @@ -51,6 +51,33 @@ from spotforecast2_safe.manager.logger import setup_logging from spotforecast2_safe.manager.tools import _parse_bool +# Default aggregation weights for the N-to-1 forecasting task. +# +# The position of each value corresponds to a specific forecast component or +# aggregation term used by `agg_predict`. Positive values increase the influence +# of the corresponding component in the final aggregated forecast, whereas +# negative values down-weight or invert the contribution of that component. +# +# NOTE: +# - These defaults are domain-specific and should be updated together with any +# changes to the aggregation logic or the ordering of components in +# `agg_predict`. +# - They are defined as a named constant (rather than inline) to make it clear +# what is being tuned and to avoid unexplained "magic numbers" in the code. +DEFAULT_WEIGHTS: List[float] = [ + 1.0, + 1.0, + -1.0, + -1.0, + 1.0, + -1.0, + 1.0, + 1.0, + 1.0, + -1.0, + 1.0, +] + warnings.simplefilter("ignore") @@ -210,11 +237,11 @@ def n_to_1_with_covariates( weights (Optional[Union[Dict[str, float], List[float], np.ndarray]]): Weights for combining multi-output predictions. Can be: - - None: Default weights [1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, 1.0, -1.0, 1.0] + - None: Uses DEFAULT_WEIGHTS (see module-level constant for values) - Dict: {"col_name": weight, ...} for specific columns - List: [w1, w2, ...] in column order - np.ndarray: Same as list - Default: None (uses default weights). + Default: None (uses DEFAULT_WEIGHTS). verbose (bool): Enable progress logging. Prints intermediate results and timestamps. @@ -324,7 +351,8 @@ def n_to_1_with_covariates( # Default weights if not provided if weights is None: - weights = [1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, 1.0, -1.0, 1.0] + # Use documented default aggregation weights instead of inline magic numbers. + weights = DEFAULT_WEIGHTS if verbose: logger.info("=" * 80) @@ -336,7 +364,8 @@ def n_to_1_with_covariates( logger.info(f" Window Size: {window_size}") logger.info(f" Lags: {lags}") logger.info(f" Train Ratio: {train_ratio}") - # SECURITY: Do not log latitude/longitude (even masked) to avoid PII in logs (CWE-312, CWE-532) + # SECURITY: Never log latitude/longitude at all to avoid PII in logs (CWE-312, CWE-532). + # Only a fixed redacted placeholder is written to the logs; no masking functions are used. logger.info(" Location: [REDACTED]") # Log timezone region only, not full timezone (security: CWE-532) logger.info(f" Region: {country_code}-{state}") @@ -467,7 +496,7 @@ def main( include_poly_features (bool): Toggle polynomial features. Default: False. verbose (bool): Toggle detailed logging. Default: False. weights (Optional[List[float]]): List of weights for prediction aggregation. - Default: [1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, 1.0, -1.0, 1.0]. + Default: DEFAULT_WEIGHTS. log_dir (Optional[Path]): Directory to save log files. If None, uses default path. logging_enabled (bool): Toggle overall logging (console and file). Default: False. """ @@ -486,7 +515,8 @@ def main( logger.addHandler(logging.NullHandler()) if weights is None: - weights = [1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, 1.0, -1.0, 1.0] + # Use a copy to avoid accidental mutation of the module-level default. + weights = DEFAULT_WEIGHTS.copy() data = fetch_data() @@ -626,7 +656,7 @@ def main( "--weights", type=float, nargs="+", - default=[1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, 1.0, -1.0, 1.0], + default=DEFAULT_WEIGHTS, help="Space-separated list of weights for prediction aggregation.", ) parser.add_argument( From 51554648c54736a81edb18edfee95f297584f334 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 11 Feb 2026 19:55:23 +0000 Subject: [PATCH 3/4] Use .copy() for DEFAULT_WEIGHTS to prevent mutation in all locations Co-authored-by: bartzbeielstein <32470350+bartzbeielstein@users.noreply.github.com> --- .../tasks/task_safe_n_to_1_with_covariates_and_dataframe.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/spotforecast2_safe/tasks/task_safe_n_to_1_with_covariates_and_dataframe.py b/src/spotforecast2_safe/tasks/task_safe_n_to_1_with_covariates_and_dataframe.py index e3a94944d..891a512d0 100644 --- a/src/spotforecast2_safe/tasks/task_safe_n_to_1_with_covariates_and_dataframe.py +++ b/src/spotforecast2_safe/tasks/task_safe_n_to_1_with_covariates_and_dataframe.py @@ -352,7 +352,8 @@ def n_to_1_with_covariates( # Default weights if not provided if weights is None: # Use documented default aggregation weights instead of inline magic numbers. - weights = DEFAULT_WEIGHTS + # Use a copy to avoid accidental mutation of the module-level default. + weights = DEFAULT_WEIGHTS.copy() if verbose: logger.info("=" * 80) From bc38050ee207f80e930ff3883f3ae4e76b6bf977 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 11 Feb 2026 19:56:12 +0000 Subject: [PATCH 4/4] Fix argparse default to avoid mutable default argument issue Co-authored-by: bartzbeielstein <32470350+bartzbeielstein@users.noreply.github.com> --- .../tasks/task_safe_n_to_1_with_covariates_and_dataframe.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/spotforecast2_safe/tasks/task_safe_n_to_1_with_covariates_and_dataframe.py b/src/spotforecast2_safe/tasks/task_safe_n_to_1_with_covariates_and_dataframe.py index 891a512d0..f43a885a2 100644 --- a/src/spotforecast2_safe/tasks/task_safe_n_to_1_with_covariates_and_dataframe.py +++ b/src/spotforecast2_safe/tasks/task_safe_n_to_1_with_covariates_and_dataframe.py @@ -657,7 +657,7 @@ def main( "--weights", type=float, nargs="+", - default=DEFAULT_WEIGHTS, + default=None, help="Space-separated list of weights for prediction aggregation.", ) parser.add_argument(