Skip to content

fix(runtime): block weekend IBKR live schedules#341

Open
Pigbibi wants to merge 4 commits into
mainfrom
fix/weekday-scheduler-force-env
Open

fix(runtime): block weekend IBKR live schedules#341
Pigbibi wants to merge 4 commits into
mainfrom
fix/weekday-scheduler-force-env

Conversation

@Pigbibi

@Pigbibi Pigbibi commented Jul 12, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • manage IBKR_FORCE_RUN through the Cloud Run env sync plan, remove it when unset, and reject true for live targets
  • default managed schedules to Mon-Fri and reject non-weekday cron for US live account targets
  • preserve the closed-market application calendar gate and cover four account-backed targets, including disabled targets

Verification

  • uv run --no-sync pytest -q tests/test_runtime_config_support.py -k 'build_cloud_run_env_sync_plan' (5 passed)
  • uv run --no-sync pytest -q tests/test_request_handling.py -k 'handle_request_post_returns_market_closed' (1 passed)
  • bash tests/test_sync_cloud_run_env_workflow.sh
  • uv run --no-sync ruff check scripts/build_cloud_run_env_sync_plan.py tests/test_runtime_config_support.py tests/test_request_handling.py
  • actionlint .github/workflows/*.yml
  • git diff --check

Safety

  • no strategy execution, scheduler invocation, broker credential, or order path was triggered
  • disabled runtime targets remain disabled

Pigbibi and others added 2 commits July 13, 2026 04:57
Co-Authored-By: Codex <noreply@openai.com>
…-force-env

Co-Authored-By: Codex <noreply@openai.com>
@github-actions

github-actions Bot commented Jul 12, 2026

Copy link
Copy Markdown

🤖 Codex PR Review

🚫 Merge blocked: contract arbitration failed closed; automatic remediation is disabled

⚖️ Codex Review Arbitration

⚠️ ambiguous: The prior high-severity cron-shape finding is no longer the source of truth: this PR now parses day-of-week semantics via _cron_days_of_week(...) and adds tests that explicitly accept weekday-only variants like 1,3,5, MON-FRI, and 2-5, so there is no contract conflict with the current suggestion. But the current finding is not proven valid from the provided source of truth. The new guard does compare market == "US" literally at scripts/build_cloud_run_env_sync_plan.py:546, yet the cumulative diff shown does not include how market is derived earlier in _build_scheduler_plan, and the added tests/documented configs only exercise uppercase "US"/"HK". That means the current source provided here does not prove whether lowercase/whitespace market inputs are part of the accepted interface or already normalized before this check.

🚫 Blocking Issues

These issues must be fixed before this PR can be merged:

1. 🟠 [HIGH] Logic in scripts/build_cloud_run_env_sync_plan.py

The new weekend-cron rejection only runs when market == "US" exactly. If a target inherits the same market as "us", "Us", or a value with surrounding whitespace, the code skips validation and allows weekend schedules for a live US account target, defeating the protection this PR is adding. (line 549)

Suggestion: Normalize the market code before the check, for example with normalized_market = str(market).strip().upper() and compare against "US".


Review by Codex PR Review bot • PR

Co-Authored-By: Codex <noreply@openai.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ae0944cf42

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +512 to +514
if len(fields) != 5 or fields[2:] != ["*", "*", "1-5"]:
raise ValueError(
f"US live account scheduler {key} must be Mon-Fri cron: {scheduler[key]!r}"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Allow monthly live scheduler windows

For US live account targets with an existing day-of-month scheduler window, such as the monthly runtime shape 45 15 1-7 * * still modeled in tests/test_execution_report_heartbeat.py and used with the monthly russell_top50_leader_rotation cadence, this exact-shape check rejects the sync plan before any Cloud Run env update can run. Those services either become unsyncable with their current monthly cron or have to be changed to run every weekday, which defeats the existing scheduler/heartbeat cadence; the live-schedule guard needs to preserve supported DOM-limited schedules instead of requiring only * * 1-5.

Useful? React with 👍 / 👎.

Comment on lines +506 to +508
market == "US"
and str(runtime_target.get("execution_mode") or "").strip().lower() == "live"
and runtime_target.get("account_selector")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Enforce weekday schedules for default-US live targets

When a live service relies on the runtime defaults for US market (IBKR_MARKET unset) or on ACCOUNT_GROUP/account-group config instead of embedding account_selector, this condition is false, so a weekend cron like 45 15 * * * is accepted even though the application defaults the market to US and resolves live accounts from the account group. This leaves a common live Cloud Run target shape outside the new weekend-schedule guard, so those services can still be synced with Saturday/Sunday schedules.

Useful? React with 👍 / 👎.

Comment on lines +456 to +459
str(runtime_target.get("execution_mode") or "").strip().lower() == "live"
and str(env_values.get("IBKR_FORCE_RUN") or "").strip().lower() == "true"
):
raise ValueError("IBKR_FORCE_RUN=true is not allowed for live Cloud Run targets")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reject force-run based on actual dry-run state

For a target whose runtime_target.execution_mode is missing or stale as paper while IBKR_DRY_RUN_ONLY is unset/false and the account group points at a live gateway, this check allows IBKR_FORCE_RUN=true into Cloud Run even though the request path uses that variable to bypass the market-hours gate and the order path is controlled by the dry-run/gateway env, not this metadata field. The guard should also require the resolved target to be dry-run/paper from the env values before allowing force-run, otherwise a config mismatch can still force live execution outside market hours.

Useful? React with 👍 / 👎.

Co-Authored-By: Codex <noreply@openai.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 669eb9090a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +549 to +553
if (
market == "US"
and str(runtime_target.get("execution_mode") or "").strip().lower() == "live"
and runtime_target.get("account_selector")
):

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Skip schedule validation for disabled targets

When a live target is already disabled with RUNTIME_TARGET_ENABLED=false but still has an old daily cron such as 45 15 * * *, this guard now aborts the entire sync plan before the workflow can keep the service disabled or clean up its env. Disabled targets do not reach the market-hours/order path in main._handle_request(), and this script already skips other required-input validation for disabled targets via _runtime_target_enabled(env_values), so applying the new weekend schedule rejection to disabled services makes safe cleanup/sync operations fail unnecessarily.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant