Skip to content

feat(research-ui): surface pretrade artifact paths#252

Merged
Whiteks1 merged 1 commit intomainfrom
codex/pretrade-intake-artifact-links
Apr 4, 2026
Merged

feat(research-ui): surface pretrade artifact paths#252
Whiteks1 merged 1 commit intomainfrom
codex/pretrade-intake-artifact-links

Conversation

@Whiteks1
Copy link
Copy Markdown
Owner

@Whiteks1 Whiteks1 commented Apr 4, 2026

Summary

Surface the validation and source artifact paths in the read-only pre-trade intake panel so the calculator handoff can be inspected without leaving the UI.

Changes included:

  • show the latest validation artifact path in research_ui
  • show the source artifact path in research_ui
  • link out to the validation artifact when it is local to QuantLab
  • keep the panel read-only and artifact-driven
  • add focused server coverage for the source/validation artifact paths

Why

The pre-trade intake panel already existed and showed the core decision state.

What was still missing was the artifact path visibility that makes the panel actually useful during operator review. This slice adds that visibility without changing validation, policy, or execution behavior.

Scope

This PR does not:

  • change pre-trade validation semantics
  • change broker execution behavior
  • embed the external calculator into QuantLab
  • add write or mutate actions to the UI

It only improves read-only intake visibility.

Validation

Validated with:

  • python -m pytest -q test/test_research_ui_server.py test/test_app_cli.py
  • node --check research_ui/app.js
  • git diff --check

Notes

  • The source artifact may live outside the QuantLab tree, so the panel shows its path even when no local href is available.
  • The validation artifact stays linked when it is local to QuantLab.
  • This keeps the boundary clear: the calculator proposes, QuantLab validates, and the UI only visualizes the result.

Closes #185

Summary by Sourcery

Surface pre-trade validation and source artifact information in the read-only research UI intake panel.

New Features:

  • Display latest validation artifact path and link in the pre-trade intake panel when available.
  • Display source artifact path in the pre-trade intake panel, with or without a local link.

Tests:

  • Extend server-side tests to assert inclusion of source and validation artifact paths in the pre-trade handoff payload.

@sourcery-ai
Copy link
Copy Markdown

sourcery-ai bot commented Apr 4, 2026

Reviewer's Guide

Adds read-only display of pre-trade validation and source artifact paths to the research UI pre-trade panel, wiring through the latest validation and source artifact metadata from the server and covering it with focused tests.

Sequence diagram for loading pretrade artifact metadata into the UI

sequenceDiagram
    actor Operator
    participant Browser_research_ui
    participant Research_ui_server
    participant Pretrade_service

    Operator->>Browser_research_ui: Select pretrade for review
    Browser_research_ui->>Research_ui_server: GET /api/pretrade/{id}
    Research_ui_server->>Pretrade_service: Fetch pretrade decision state
    Pretrade_service-->>Research_ui_server: pretrade core fields
    Research_ui_server->>Pretrade_service: Fetch artifact metadata
    Pretrade_service-->>Research_ui_server: latest_validation_path, latest_validation_href, source_artifact_path, source_artifact_href
    Research_ui_server-->>Browser_research_ui: pretrade JSON with artifact fields
    Browser_research_ui->>Browser_research_ui: buildPretradePanel(pretrade)
    Browser_research_ui->>Browser_research_ui: Render artifactLinks list or empty placeholder
    Operator-->>Browser_research_ui: Optionally click validation artifact link
    Browser_research_ui-->>Operator: Open validation artifact in new tab
Loading

Flow diagram for rendering artifact links in buildPretradePanel

flowchart TD
    A["Start buildPretradePanel"] --> B["Initialize artifactEntries with validation and source artifacts"]
    B --> C{"artifact.path or artifact.href for any entry?"}
    C -->|No| D["Render panel-empty compact-empty with No artifact paths yet message"]
    C -->|Yes| E["Filter artifactEntries to those with path or href"]
    E --> F["Map each artifact to DOM fragment"]
    F --> G{"artifact.href present?"}
    G -->|Yes| H["Render a.artifact-link with label and path, target _blank"]
    G -->|No| I["Render div.artifact-link with label and path_or_fallback"]
    H --> J["Join fragments into artifact-list container"]
    I --> J
    J --> K["Inject artifactLinks HTML into pretrade panel below key-value grid"]
    K --> L["Render reasons inline-list"]
    L --> M["End buildPretradePanel"]
Loading

File-Level Changes

Change Details Files
Render validation and source artifact metadata in the pre-trade intake panel UI.
  • Build a normalized list of validation/source artifact entries from the pretrade payload, including labels, paths, hrefs, and fallback copy.
  • Render artifact entries as either external links (when href exists) or static rows (when only paths are available), escaping all dynamic content.
  • Show an empty-state message when no artifact metadata is present and insert the artifact block between the main key-value grid and the rejection reasons list.
research_ui/app.js
Extend server-side pre-trade handoff payload to include source artifact metadata and test it.
  • Verify that the pre-trade handoff payload now includes source_artifact_path populated from the test fixture and a null source_artifact_href.
  • Confirm latest_validation_path and latest_validation_href behavior is unchanged while asserting the additional artifact fields.
test/test_research_ui_server.py

Assessment against linked issues

Issue Objective Addressed Explanation
#185 Provide a read-only pre-trade intake panel in research_ui that visualizes the latest pre-trade handoff validation state (including accepted/rejected status, rejection reasons, symbol, venue, side, ready_for_draft_execution_intent) and shows an honest empty state when no validation artifact exists.
#185 Surface the latest handoff’s validation and source artifact paths in the pre-trade intake panel, with optional links when local, while keeping the panel strictly read-only and artifact-driven.

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Copy Markdown

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey - I've found 1 issue, and left some high level feedback:

  • The artifactEntries filter drops artifacts that have neither path nor href, which means the per-artifact fallback messages are never shown; consider removing or adjusting the filter so each artifact row can display its specific fallback copy instead of only the global empty state.
  • The test test_build_pretrade_handoff_payload_selects_latest_validation_artifact hardcodes an absolute Windows-specific source path (C:\Users\marce\...), which will be brittle and non-portable; derive this path from a fixture or tmp_path instead.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The `artifactEntries` filter drops artifacts that have neither `path` nor `href`, which means the per-artifact `fallback` messages are never shown; consider removing or adjusting the filter so each artifact row can display its specific fallback copy instead of only the global empty state.
- The test `test_build_pretrade_handoff_payload_selects_latest_validation_artifact` hardcodes an absolute Windows-specific source path (`C:\Users\marce\...`), which will be brittle and non-portable; derive this path from a fixture or `tmp_path` instead.

## Individual Comments

### Comment 1
<location path="test/test_research_ui_server.py" line_range="514-515" />
<code_context>
     assert payload["handoff_id"] == "handoff-newer"
     assert payload["latest_validation_path"] == str(newer)
     assert payload["latest_validation_href"] == "/outputs/pretrade_handoff/newer/pretrade_handoff_validation.json"
+    assert payload["source_artifact_path"] == "C:\\Users\\marce\\Documents\\meta_trade\\tests\\fixtures\\expected_quantlab_handoff.json"
+    assert payload["source_artifact_href"] is None


</code_context>
<issue_to_address>
**issue (testing):** Avoid asserting on a hard-coded, absolute, Windows-specific path in the test

This hard-coded, user-specific Windows path will make the test fail on CI and on non-Windows or differently configured machines. Instead, derive the expected value from the test paths/fixtures already in use (e.g., via `tmp_path` or a known fixture root) and compare a constructed or normalized path (using `os.path.join` / `os.path.normpath`, or checking a relative suffix) so the test validates the contract without depending on a specific machine layout.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines +514 to +515
assert payload["source_artifact_path"] == "C:\\Users\\marce\\Documents\\meta_trade\\tests\\fixtures\\expected_quantlab_handoff.json"
assert payload["source_artifact_href"] is None
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

issue (testing): Avoid asserting on a hard-coded, absolute, Windows-specific path in the test

This hard-coded, user-specific Windows path will make the test fail on CI and on non-Windows or differently configured machines. Instead, derive the expected value from the test paths/fixtures already in use (e.g., via tmp_path or a known fixture root) and compare a constructed or normalized path (using os.path.join / os.path.normpath, or checking a relative suffix) so the test validates the contract without depending on a specific machine layout.

@Whiteks1 Whiteks1 merged commit 9222ab6 into main Apr 4, 2026
2 checks passed
@Whiteks1 Whiteks1 deleted the codex/pretrade-intake-artifact-links branch April 4, 2026 16:49
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.

research_ui: add read-only pre-trade intake panel for calculator handoff

1 participant