Claude/optimistic mendel g1xjts - #176
Open
jkirkmannz wants to merge 4 commits into
Open
Conversation
…80985157 Add Claude Code GitHub Workflow
Consolidates the unified MarketDataSource interface, GBM simulator, and Massive API client into one canonical design doc reflecting the as-built implementation in backend/app/market/, including fixes applied during code review (top-level massive import, public GBMSimulator.get_tickers(), corrected SSE generator typing). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GAiyqJ7iF92GJvyR5FtPYD
There was a problem hiding this comment.
🟡 Changes recommended
An unresolved critical workflow permission issue and multiple correctness findings remain.
Get a fresh assessment by requesting another Copilot review.
Pull request overview
Adds market-data design documentation and updates Claude PR-review workflows to support inline comments.
Changes:
- Documents market-data architecture, lifecycle, SSE, APIs, and testing.
- Enables Claude inline review comments.
- Updates the Claude CLI permission example.
File summaries
| File | Summary and findings |
|---|---|
planning/MARKET_DATA_DESIGN.md |
Adds the market-data design reference. Findings: Moderate (3 votes): ticker removal must advance _version; timestamp=0 must be preserved; empty snapshots must be emitted; and in-flight polling must not re-add removed tickers. Moderate (1 vote): gate cache mutations after simulator shutdown. Moderate (3 votes): create a fresh router per factory call. Moderate (2 votes): normalize simulator tickers at the API boundary. Nit (1 vote): preserve held positions when removing tickers; initialize _client in the polling example; mark missing app wiring as pending or implement it. Nit (2 votes): update the test count from 17 to 19. |
.github/workflows/claude.yml |
Updates the commented CLI permission example. Nit (1 vote): retain the documented Bash(gh pr:*) matcher form. |
.github/workflows/claude-code-review.yml |
Enables inline review comments. Critical (3 votes): grant pull-requests: write; read permission causes comment creation to fail with 403. |
Review details
Suppressed comments (6)
.github/workflows/claude.yml:49
- This changes the Claude Code permission matcher from
Bash(gh pr:*)toBash(gh pr *). The Claude Code command definitions use thecommand:*form for prefix matches; the space form is not the documented matcher and may fail to allowgh prsubcommands when this example is uncommented. Keep the colon form or use an exact command rule.
# claude_args: '--allowed-tools Bash(gh pr *)'
planning/MARKET_DATA_DESIGN.md:305
- This contract is not met by the implementations shown below: after
SimulatorDataSource.stop()leaves_simset,add_ticker()can still callcache.update(), and both implementations'remove_ticker()still mutate the cache after stop. A request after shutdown can therefore change the cache. Gate mutators on a running state (or clear/disable it) and add a regression test.
Safe to call multiple times. After stop(), the source will not write
to the cache again.
planning/MARKET_DATA_DESIGN.md:1148
- This route example unconditionally calls
source.remove_ticker()after deleting the watchlist row, but the next section says held positions must remain tracked for valuation. Following this earlier snippet would remove prices for open positions. Include the position check here too, or clearly mark this as pseudocode that must not be copied.
await source.remove_ticker(ticker)
planning/MARKET_DATA_DESIGN.md:1280
_poll_once()returns immediately when_clientisNone, but this example never assignssource._client; it will leave the cache empty and make both assertions fail. Add the samesource._client = MagicMock()setup used by the actual test before calling_poll_once().
source = MassiveDataSource(api_key="test-key", price_cache=cache, poll_interval=60.0)
source._tickers = ["AAPL", "BAD"]
planning/MARKET_DATA_DESIGN.md:1068
- This section is presented as implemented, but the checkout has no
backend/app/main.pyor other FastAPI app wiring: nothing creates the lifespan, starts the source, or mounts this router. As written,/api/stream/pricesand the background feed are not exposed despite the status claiming the design is complete; either mark this integration as pending or add the application wiring before making that claim.
## 13. FastAPI Lifecycle Integration
The market data system starts and stops with the FastAPI app via the `lifespan` context manager.
**In `backend/app/main.py`:**
planning/MARKET_DATA_DESIGN.md:1002
- The stream sends full snapshots, but this guard suppresses the event when the snapshot is empty. Even after a removal increments the cache version, deleting the last ticker will therefore never send
{}and clients cannot clear their stale entry. Serialize and yield the empty snapshot whenever the version changes.
if prices:
data = {ticker: update.to_dict() for ticker, update in prices.items()}
yield f"data: {json.dumps(data)}\n\n"
- Files reviewed: 3/3 changed files
- Comments generated: 7
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| plugins: 'code-review@claude-code-plugins' | ||
| prompt: '/code-review:code-review ${{ github.repository }}/pull/${{ github.event.pull_request.number }}' | ||
| prompt: '/code-review:code-review --comment ${{ github.repository }}/pull/${{ github.event.pull_request.number }}' | ||
| claude_args: '--allowedTools "mcp__github_inline_comment__create_inline_comment"' |
| If this is the first update for the ticker, previous_price == price (direction='flat'). | ||
| """ | ||
| with self._lock: | ||
| ts = timestamp or time.time() |
Comment on lines
+223
to
+224
| with self._lock: | ||
| self._prices.pop(ticker, None) |
Comment on lines
+838
to
+842
| try: | ||
| price = snap.last_trade.price | ||
| # Massive timestamps are Unix milliseconds -> convert to seconds | ||
| timestamp = snap.last_trade.timestamp / 1000.0 | ||
| self._cache.update(ticker=snap.ticker, price=price, timestamp=timestamp) |
|
|
||
| - **`massive` is a top-level import**, not a lazy one. Since `massive>=1.0.0` is a core dependency in `pyproject.toml` (not optional), the module-level import is simpler and — importantly — makes `unittest.mock.patch("app.market.massive_client.RESTClient")` work directly in tests without `create=True`. | ||
| - **Error handling is deliberately resilient**, not defensive-for-its-own-sake: a bad ticker's snapshot is skipped and logged (`AttributeError`/`TypeError`), a wholesale poll failure (network error, 401, 429) is logged and the loop simply tries again next interval. The cache retains its last-known values in the meantime — stale data displayed is preferable to the feed dying. | ||
| - **Ticker normalization** (`.upper().strip()`) happens in `add_ticker`/`remove_ticker` so watchlist input from the UI or LLM chat doesn't need to pre-sanitize ticker casing. |
| This factory pattern injects the PriceCache without module-level globals. | ||
| """ | ||
|
|
||
| @router.get("/prices") |
| |---|---|---|---| | ||
| | `test_models.py` | 11 | 100% | `PriceUpdate` computed properties, `to_dict()` | | ||
| | `test_cache.py` | 13 | 100% | Update/get/remove, version counter, first-update-is-flat | | ||
| | `test_simulator.py` | 17 | 98% | GBM math correctness, add/remove ticker, Cholesky rebuild, edge cases | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.