Skip to content

H-6664: Introduce Python monorepo infrastructure and formalize python repo-chores#9039

Open
indietyp wants to merge 9 commits into
mainfrom
bm/h-6664-python-monorepo-infrastructure
Open

H-6664: Introduce Python monorepo infrastructure and formalize python repo-chores#9039
indietyp wants to merge 9 commits into
mainfrom
bm/h-6664-python-monorepo-infrastructure

Conversation

@indietyp

Copy link
Copy Markdown
Member

🌟 What is the purpose of this PR?

This PR establishes a first-class Python workspace for the monorepo, built on a single uv workspace rooted at a new pyproject.toml. All Python packages share one lockfile (uv.lock), one virtual environment, and workspace-level tooling: ruff for linting and formatting, ty for type checking, tach for import-boundary enforcement, and pytest for tests.

A new Python package, libs/@local/repo-chores/python (hash-repo-chores), acts as the Python counterpart to the existing Rust sync-turborepo tooling. It provides a repo-chores CLI with two subcommands:

  • sync — enforces workspace invariants: explicit uv workspace membership, uniform requires-python bounds, shared ruff/pytest dev pins, and per-member package.json turbo wiring (@python/<name> with managed lint:ruff, fix:ruff, and test:unit scripts).
  • prune — extends the existing turbo prune logic (previously a standalone script at .github/actions/prune-repository/prune.py) to also stub out pruned uv workspace members, keeping the pruned output a valid uv workspace.

CI gains a lint:python step that runs uv sync --locked (lockfile stability), repo-chores sync --check (workspace drift), ruff, ty, and tach. A fix:python step applies ruff autofixes and refreshes the lock. A sync:python mise task regenerates all managed wiring after adding, removing, or renaming a Python package. The lefthook pre-commit hook gains a Python entry that runs ruff on staged .py files.

🔍 What does this change?

  • Adds a root pyproject.toml and uv.lock establishing the uv workspace, pinned to Python 3.14, with ruff, ty, tach, and pytest configured workspace-wide.
  • Introduces libs/@local/repo-chores/python (hash-repo-chores) with modules for workspace discovery (workspace.py), TOML in-place editing (toml_edit.py), workspace sync (sync.py), turbo pruning (prune.py), and a CLI entry point (cli.py).
  • Moves .github/actions/prune-repository/prune.py into libs/@local/repo-chores/python/repo_chores/prune.py, refactoring it to be path-aware, stdlib-only, and callable both directly and via repo-chores prune. Adds stub_missing_uv_members so pruned uv workspace members are stubbed back in alongside Cargo stubs.
  • Updates the prune-repository GitHub Action to invoke the script from its new location and to copy pyproject.toml and uv.lock into the pruned output.
  • Adds mise tasks lint:python, fix:python, and sync:python wrapping the corresponding uv/repo-chores invocations.
  • Adds lint:python and fix:python yarn scripts in the root package.json delegating to the mise tasks.
  • Adds lint:ruff and fix:ruff turbo pipeline entries so per-package ruff runs participate in the turbo graph.
  • Extends the CI lint workflow to detect and run lint:ruff per package and to run yarn lint:python globally.
  • Adds .ruff_cache to .gitignore and .dockerignore.
  • Adds a lefthook pre-commit hook that runs ruff check and format on staged Python files.
  • Bumps uv from 0.11.18 to 0.11.28 with updated checksums for all platforms.
  • Documents the Python workspace setup in README.md and AGENTS.md, including how to add packages, run checks, and interpret the sync tooling.
  • Adds a full test suite for hash-repo-chores covering prune logic, workspace discovery, sync check/fix/idempotency, and assemble_package_json.

Pre-Merge Checklist 🚀

🚢 Has this modified a publishable library?

This PR:

  • does not modify any publishable blocks or libraries, or modifications do not need publishing

📜 Does this require a change to the docs?

The changes in this PR:

  • require changes to docs which are made as part of this PR

🕸️ Does this require a change to the Turbo Graph?

The changes in this PR:

  • affected the execution graph, and the turbo.json's have been updated to reflect this

🛡 What tests cover this?

  • New pytest suite in libs/@local/repo-chores/python/tests/ covering test_prune.py, test_sync.py, and test_workspace.py with a shared conftest.py fixture repository.

❓ How to test this?

  1. Run mise install to provision uv 0.11.28.
  2. Run uv sync to create the virtual environment.
  3. Run mise run lint:python and confirm all checks pass.
  4. Run mise run fix:python and confirm ruff autofixes apply cleanly.
  5. Run mise run sync:python and confirm no drift is reported on a second mise run lint:python.
  6. Run uv run --frozen pytest libs/@local/repo-chores/python/tests and confirm all tests pass.

@indietyp
indietyp requested a review from a team as a code owner July 15, 2026 21:48
Copilot AI review requested due to automatic review settings July 15, 2026 21:48
@vercel

vercel Bot commented Jul 15, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
hash Ready Ready Preview, Comment Jul 27, 2026 9:11am
hashdotdesign-tokens Ready Ready Preview, Comment Jul 27, 2026 9:11am
petrinaut Ready Ready Preview, Comment Jul 27, 2026 9:11am

@cursor

cursor Bot commented Jul 15, 2026

Copy link
Copy Markdown

PR Summary

Medium Risk
Touches CI gates and the petrinaut optimization service (subprocess CLI, streaming, admission control); infra-only areas are low risk but service refactors warrant careful review.

Overview
Introduces first-class Python workspace tooling alongside the existing Rust/JS monorepo: uv is bumped to 0.11.28, and new mise tasks run lint:python, fix:python, and sync:python (lock stability, repo-chores sync --check, dependency lint, ruff, ty, tach). Root yarn scripts delegate to those tasks; CI gains per-package lint:ruff via Turbo and a global yarn lint:python step with local-fix hints. Lefthook auto-fixes staged *.py with ruff.

Prune-repository now runs repo-chores/prune.py from libs/@local/repo-chores/python (stdlib-only, pre-install) and copies pyproject.toml / uv.lock into pruned trees so Turbo prunes stay valid uv workspaces. .ruff_cache is ignored for git and Docker.

apps/petrinaut-opt is wired as @python/petrinaut-optimization with managed lint:ruff / fix:ruff scripts, Python 3.14 bounds, and stricter typing (Pydantic models, protocols, JsonValue in OpenAPI). The optimization API, CLI client, optimizer SSE paths, and telemetry are refactored for type-checking and test seams without changing the external SSE contract. Docs in README and AGENTS.md describe the Python workflow.

Reviewed by Cursor Bugbot for commit ebb40a5. Bugbot is set up for automated code reviews on this repo. Configure here.

@github-actions github-actions Bot added area/deps Relates to third-party dependencies (area) area/infra Relates to version control, CI, CD or IaC (area) area/libs Relates to first-party libraries/crates/packages (area) type/eng > backend Owned by the @backend team area/tests New or updated tests type/legal Owned by the @legal team labels Jul 15, 2026

Copy link
Copy Markdown
Member Author

This stack of pull requests is managed by Graphite. Learn more about stacking.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Comment thread libs/@local/repo-chores/python/repo_chores/sync.py Outdated
Comment thread libs/@local/repo-chores/python/repo_chores/sync.py
Comment thread pyproject.toml Fixed
Comment thread pyproject.toml Outdated
@codspeed-hq

codspeed-hq Bot commented Jul 15, 2026

Copy link
Copy Markdown

Merging this PR will degrade performance by 15.38%

❌ 2 regressed benchmarks
✅ 96 untouched benchmarks

Warning

Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Benchmark BASE HEAD Efficiency
bit_matrix/dense/iter_row[64] 140.8 ns 170 ns -17.16%
bit_matrix/dense/iter_row[200] 185.8 ns 215 ns -13.57%

Tip

Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.


Comparing bm/h-6664-python-monorepo-infrastructure (8a662f1) with main (0cb749d)1

Open in CodSpeed

Footnotes

  1. No successful run was found on main (0465623) during the generation of this report, so 0cb749d was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

Copilot AI review requested due to automatic review settings July 15, 2026 22:14

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Comment thread pyproject.toml Outdated
Comment thread pyproject.toml Fixed
Comment thread pyproject.toml
Copilot AI review requested due to automatic review settings July 16, 2026 01:14
@vercel
vercel Bot temporarily deployed to Preview – petrinaut July 16, 2026 01:14 Inactive

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Copilot AI review requested due to automatic review settings July 16, 2026 08:13
@vercel
vercel Bot temporarily deployed to Preview – petrinaut July 16, 2026 08:13 Inactive

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Comment thread libs/@local/repo-chores/python/repo_chores/sync.py
Comment thread pyproject.toml
@github-actions

Copy link
Copy Markdown
Contributor

Benchmark results

@rust/hash-graph-benches – Integrations

policy_resolution_large

Function Value Mean Flame graphs
resolve_policies_for_actor user: empty, selectivity: high, policies: 2002 $$26.7 \mathrm{ms} \pm 209 \mathrm{μs}\left({\color{gray}-3.694 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: low, policies: 1 $$3.37 \mathrm{ms} \pm 22.4 \mathrm{μs}\left({\color{gray}-0.748 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: medium, policies: 1002 $$12.0 \mathrm{ms} \pm 94.7 \mathrm{μs}\left({\color{lightgreen}-7.880 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: high, policies: 3314 $$42.1 \mathrm{ms} \pm 398 \mathrm{μs}\left({\color{gray}-2.627 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: low, policies: 1 $$14.0 \mathrm{ms} \pm 139 \mathrm{μs}\left({\color{gray}-0.886 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: medium, policies: 1527 $$23.5 \mathrm{ms} \pm 198 \mathrm{μs}\left({\color{gray}-3.149 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: high, policies: 2078 $$27.8 \mathrm{ms} \pm 180 \mathrm{μs}\left({\color{gray}-3.213 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: low, policies: 1 $$3.67 \mathrm{ms} \pm 21.5 \mathrm{μs}\left({\color{gray}-1.050 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: medium, policies: 1033 $$13.2 \mathrm{ms} \pm 127 \mathrm{μs}\left({\color{lightgreen}-7.633 \mathrm{\%}}\right) $$ Flame Graph

policy_resolution_medium

Function Value Mean Flame graphs
resolve_policies_for_actor user: empty, selectivity: high, policies: 102 $$3.76 \mathrm{ms} \pm 26.3 \mathrm{μs}\left({\color{gray}-1.010 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: low, policies: 1 $$3.00 \mathrm{ms} \pm 20.5 \mathrm{μs}\left({\color{gray}1.14 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: medium, policies: 52 $$3.35 \mathrm{ms} \pm 18.6 \mathrm{μs}\left({\color{gray}0.728 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: high, policies: 269 $$5.16 \mathrm{ms} \pm 31.3 \mathrm{μs}\left({\color{gray}-0.832 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: low, policies: 1 $$3.53 \mathrm{ms} \pm 21.4 \mathrm{μs}\left({\color{gray}-0.430 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: medium, policies: 108 $$4.13 \mathrm{ms} \pm 30.0 \mathrm{μs}\left({\color{gray}0.204 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: high, policies: 133 $$4.45 \mathrm{ms} \pm 30.3 \mathrm{μs}\left({\color{gray}0.060 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: low, policies: 1 $$3.40 \mathrm{ms} \pm 17.9 \mathrm{μs}\left({\color{gray}-0.173 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: medium, policies: 63 $$4.23 \mathrm{ms} \pm 31.1 \mathrm{μs}\left({\color{gray}0.206 \mathrm{\%}}\right) $$ Flame Graph

policy_resolution_none

Function Value Mean Flame graphs
resolve_policies_for_actor user: empty, selectivity: high, policies: 2 $$2.67 \mathrm{ms} \pm 11.6 \mathrm{μs}\left({\color{gray}-0.394 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: low, policies: 1 $$2.67 \mathrm{ms} \pm 14.1 \mathrm{μs}\left({\color{gray}0.024 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: medium, policies: 2 $$2.78 \mathrm{ms} \pm 15.8 \mathrm{μs}\left({\color{gray}1.23 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: high, policies: 8 $$3.02 \mathrm{ms} \pm 17.3 \mathrm{μs}\left({\color{gray}-0.332 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: low, policies: 1 $$2.81 \mathrm{ms} \pm 17.5 \mathrm{μs}\left({\color{gray}0.474 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: medium, policies: 3 $$3.10 \mathrm{ms} \pm 16.7 \mathrm{μs}\left({\color{gray}0.202 \mathrm{\%}}\right) $$ Flame Graph

policy_resolution_small

Function Value Mean Flame graphs
resolve_policies_for_actor user: empty, selectivity: high, policies: 52 $$3.07 \mathrm{ms} \pm 17.7 \mathrm{μs}\left({\color{gray}-0.184 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: low, policies: 1 $$2.74 \mathrm{ms} \pm 14.3 \mathrm{μs}\left({\color{gray}-0.120 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: medium, policies: 26 $$2.91 \mathrm{ms} \pm 15.8 \mathrm{μs}\left({\color{gray}-0.041 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: high, policies: 94 $$3.50 \mathrm{ms} \pm 21.8 \mathrm{μs}\left({\color{gray}1.58 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: low, policies: 1 $$2.97 \mathrm{ms} \pm 16.8 \mathrm{μs}\left({\color{gray}-1.310 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: medium, policies: 27 $$3.25 \mathrm{ms} \pm 17.2 \mathrm{μs}\left({\color{gray}-0.203 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: high, policies: 66 $$3.39 \mathrm{ms} \pm 24.4 \mathrm{μs}\left({\color{gray}-0.863 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: low, policies: 1 $$3.00 \mathrm{ms} \pm 16.8 \mathrm{μs}\left({\color{gray}0.161 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: medium, policies: 29 $$3.32 \mathrm{ms} \pm 16.4 \mathrm{μs}\left({\color{gray}-0.366 \mathrm{\%}}\right) $$ Flame Graph

read_scaling_complete

Function Value Mean Flame graphs
entity_by_id;one_depth 1 entities $$32.1 \mathrm{ms} \pm 172 \mathrm{μs}\left({\color{gray}-0.403 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;one_depth 10 entities $$71.8 \mathrm{ms} \pm 481 \mathrm{μs}\left({\color{gray}2.35 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;one_depth 25 entities $$35.8 \mathrm{ms} \pm 185 \mathrm{μs}\left({\color{gray}-0.071 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;one_depth 5 entities $$39.8 \mathrm{ms} \pm 226 \mathrm{μs}\left({\color{gray}1.52 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;one_depth 50 entities $$42.4 \mathrm{ms} \pm 249 \mathrm{μs}\left({\color{gray}4.49 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;two_depth 1 entities $$34.4 \mathrm{ms} \pm 192 \mathrm{μs}\left({\color{gray}3.54 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;two_depth 10 entities $$415 \mathrm{ms} \pm 1.29 \mathrm{ms}\left({\color{gray}0.457 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;two_depth 25 entities $$89.5 \mathrm{ms} \pm 591 \mathrm{μs}\left({\color{gray}-0.359 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;two_depth 5 entities $$79.0 \mathrm{ms} \pm 464 \mathrm{μs}\left({\color{gray}1.43 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;two_depth 50 entities $$268 \mathrm{ms} \pm 850 \mathrm{μs}\left({\color{gray}-1.319 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;zero_depth 1 entities $$10.9 \mathrm{ms} \pm 83.9 \mathrm{μs}\left({\color{gray}2.49 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;zero_depth 10 entities $$11.0 \mathrm{ms} \pm 70.1 \mathrm{μs}\left({\color{gray}2.72 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;zero_depth 25 entities $$11.2 \mathrm{ms} \pm 63.4 \mathrm{μs}\left({\color{gray}4.11 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;zero_depth 5 entities $$10.9 \mathrm{ms} \pm 55.7 \mathrm{μs}\left({\color{gray}1.48 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;zero_depth 50 entities $$11.0 \mathrm{ms} \pm 68.3 \mathrm{μs}\left({\color{gray}2.76 \mathrm{\%}}\right) $$ Flame Graph

read_scaling_linkless

Function Value Mean Flame graphs
entity_by_id 1 entities $$10.8 \mathrm{ms} \pm 53.4 \mathrm{μs}\left({\color{gray}2.09 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id 10 entities $$11.2 \mathrm{ms} \pm 101 \mathrm{μs}\left({\color{gray}4.66 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id 100 entities $$10.8 \mathrm{ms} \pm 88.5 \mathrm{μs}\left({\color{gray}0.259 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id 1000 entities $$11.0 \mathrm{ms} \pm 71.4 \mathrm{μs}\left({\color{gray}1.52 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id 10000 entities $$10.9 \mathrm{ms} \pm 63.9 \mathrm{μs}\left({\color{gray}-0.185 \mathrm{\%}}\right) $$ Flame Graph

representative_read_entity

Function Value Mean Flame graphs
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/block/v/1 $$11.5 \mathrm{ms} \pm 77.5 \mathrm{μs}\left({\color{gray}1.48 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/book/v/1 $$11.5 \mathrm{ms} \pm 77.3 \mathrm{μs}\left({\color{gray}-1.280 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/building/v/1 $$11.3 \mathrm{ms} \pm 61.9 \mathrm{μs}\left({\color{gray}0.945 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/organization/v/1 $$11.5 \mathrm{ms} \pm 92.8 \mathrm{μs}\left({\color{gray}0.570 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/page/v/2 $$11.4 \mathrm{ms} \pm 76.6 \mathrm{μs}\left({\color{gray}2.28 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/person/v/1 $$11.1 \mathrm{ms} \pm 48.5 \mathrm{μs}\left({\color{gray}-0.910 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/playlist/v/1 $$11.3 \mathrm{ms} \pm 65.2 \mathrm{μs}\left({\color{gray}0.895 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/song/v/1 $$11.4 \mathrm{ms} \pm 71.8 \mathrm{μs}\left({\color{gray}-0.895 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/uk-address/v/1 $$11.2 \mathrm{ms} \pm 58.9 \mathrm{μs}\left({\color{gray}-3.113 \mathrm{\%}}\right) $$ Flame Graph

representative_read_entity_type

Function Value Mean Flame graphs
get_entity_type_by_id Account ID: bf5a9ef5-dc3b-43cf-a291-6210c0321eba $$8.30 \mathrm{ms} \pm 44.3 \mathrm{μs}\left({\color{gray}0.741 \mathrm{\%}}\right) $$ Flame Graph

representative_read_multiple_entities

Function Value Mean Flame graphs
entity_by_property traversal_paths=0 0 $$58.5 \mathrm{ms} \pm 455 \mathrm{μs}\left({\color{gray}4.40 \mathrm{\%}}\right) $$
entity_by_property traversal_paths=255 1,resolve_depths=inherit:1;values:255;properties:255;links:127;link_dests:126;type:true $$110 \mathrm{ms} \pm 598 \mathrm{μs}\left({\color{gray}3.12 \mathrm{\%}}\right) $$
entity_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:0;properties:0;links:0;link_dests:0;type:false $$65.2 \mathrm{ms} \pm 374 \mathrm{μs}\left({\color{gray}3.72 \mathrm{\%}}\right) $$
entity_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:0;properties:0;links:1;link_dests:0;type:true $$74.7 \mathrm{ms} \pm 486 \mathrm{μs}\left({\color{gray}4.60 \mathrm{\%}}\right) $$
entity_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:0;properties:2;links:1;link_dests:0;type:true $$83.4 \mathrm{ms} \pm 494 \mathrm{μs}\left({\color{gray}3.87 \mathrm{\%}}\right) $$
entity_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:2;properties:2;links:1;link_dests:0;type:true $$88.3 \mathrm{ms} \pm 489 \mathrm{μs}\left({\color{gray}2.85 \mathrm{\%}}\right) $$
link_by_source_by_property traversal_paths=0 0 $$45.8 \mathrm{ms} \pm 270 \mathrm{μs}\left({\color{gray}2.68 \mathrm{\%}}\right) $$
link_by_source_by_property traversal_paths=255 1,resolve_depths=inherit:1;values:255;properties:255;links:127;link_dests:126;type:true $$72.0 \mathrm{ms} \pm 323 \mathrm{μs}\left({\color{gray}-2.727 \mathrm{\%}}\right) $$
link_by_source_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:0;properties:0;links:0;link_dests:0;type:false $$51.0 \mathrm{ms} \pm 277 \mathrm{μs}\left({\color{gray}-0.683 \mathrm{\%}}\right) $$
link_by_source_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:0;properties:0;links:1;link_dests:0;type:true $$59.7 \mathrm{ms} \pm 366 \mathrm{μs}\left({\color{gray}-1.286 \mathrm{\%}}\right) $$
link_by_source_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:0;properties:2;links:1;link_dests:0;type:true $$62.1 \mathrm{ms} \pm 428 \mathrm{μs}\left({\color{gray}0.433 \mathrm{\%}}\right) $$
link_by_source_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:2;properties:2;links:1;link_dests:0;type:true $$62.2 \mathrm{ms} \pm 401 \mathrm{μs}\left({\color{gray}-0.208 \mathrm{\%}}\right) $$

scenarios

Function Value Mean Flame graphs
full_test query-limited $$122 \mathrm{ms} \pm 531 \mathrm{μs}\left({\color{gray}-2.321 \mathrm{\%}}\right) $$ Flame Graph
full_test query-unlimited $$133 \mathrm{ms} \pm 641 \mathrm{μs}\left({\color{gray}-2.947 \mathrm{\%}}\right) $$ Flame Graph
linked_queries query-limited $$23.5 \mathrm{ms} \pm 144 \mathrm{μs}\left({\color{gray}-3.975 \mathrm{\%}}\right) $$ Flame Graph
linked_queries query-unlimited $$529 \mathrm{ms} \pm 1.06 \mathrm{ms}\left({\color{lightgreen}-5.179 \mathrm{\%}}\right) $$ Flame Graph

@indietyp
indietyp force-pushed the bm/h-6664-python-monorepo-infrastructure branch from 8a662f1 to ebb40a5 Compare July 27, 2026 08:52
@github-actions

Copy link
Copy Markdown
Contributor

Dependency Review

The following issues were found:
  • ❌ 1 vulnerable package(s)
  • ✅ 0 package(s) with incompatible licenses
  • ✅ 0 package(s) with invalid SPDX license definitions
  • ⚠️ 34 package(s) with unknown licenses.
See the Details below.

Vulnerabilities

uv.lock

NameVersionVulnerabilitySeverityPatched Version
gitpython3.1.50GitPython unsafe clone option gate bypass through joined short optionshigh3.1.51
GitPython: Command Injection via git long-option prefix abbreviation bypass of CVE-2026-42215 blocklisthigh3.1.51
GitPython: command injection via unguarded Git options in `Repo.archive()`, `git.ls_remote()`, and arbitrary file overwrite via `Repo.iter_commits()` / `Repo.blame()`high3.1.51
GitPython: Environment-variable exfiltration via os.path.expandvars() on Repo.clone_from() URLhigh3.1.52
GitPython: git-config section-name injection enables arbitrary config directives (core.sshCommand RCE)high3.1.53
GitPython: Arbitrary file overwrite via git diff --output argument injection in Diffable.diff (key- and value-controlled)high3.1.54
GitPython: Incomplete unsafe_git_clone_options denylist omits --template enabling arbitrary command execution via clone hookshigh3.1.54
GitPython: Unsafe git option guard bypass via single-character kwarg value token smuggling enables arbitrary command executionhigh3.1.54
GitPython: Environment-variable exfiltration via Repo.create_remote() / Remote.add() URL (incomplete fix of GHSA-rwj8-pgh3-r573)high3.1.55

License Issues

libs/@local/repo-chores/python/pyproject.toml

PackageVersionLicenseIssue Type
packaging>= 26.2,< 27NullUnknown License
tomlkit>= 0.15,< 0.16NullUnknown License

uv.lock

PackageVersionLicenseIssue Type
alembic1.18.5NullUnknown License
anyio4.14.2NullUnknown License
fastapi0.139.2NullUnknown License
googleapis-common-protos1.75.0NullUnknown License
greenlet3.5.3NullUnknown License
grpcio1.82.1NullUnknown License
httpcore22.7.0NullUnknown License
httptools0.8.0NullUnknown License
httpx22.7.0NullUnknown License
opentelemetry-api1.44.0NullUnknown License
opentelemetry-exporter-otlp-proto-common1.44.0NullUnknown License
opentelemetry-exporter-otlp-proto-grpc1.44.0NullUnknown License
opentelemetry-exporter-otlp-proto-http1.44.0NullUnknown License
opentelemetry-instrumentation0.65b0NullUnknown License
opentelemetry-instrumentation-asgi0.65b0NullUnknown License
opentelemetry-instrumentation-fastapi0.65b0NullUnknown License
opentelemetry-proto1.44.0NullUnknown License
opentelemetry-sdk1.44.0NullUnknown License
opentelemetry-semantic-conventions0.65b0NullUnknown License
opentelemetry-util-http0.65b0NullUnknown License
optuna4.9.0NullUnknown License
ruff0.15.21NullUnknown License
sqlalchemy2.0.51NullUnknown License
starlette1.3.1NullUnknown License
tach0.35.0NullUnknown License
tomlkit0.15.0NullUnknown License
tqdm4.69.0NullUnknown License
uvicorn0.51.0NullUnknown License
websockets16.1.1NullUnknown License
wrapt2.2.2NullUnknown License
certifi2026.7.22NullUnknown License

yarn.lock

PackageVersionLicenseIssue Type
@python/hash-repo-chores@workspace:libs/0.0.0-use.localNullUnknown License

OpenSSF Scorecard

Scorecard details
PackageVersionScoreDetails
npm/@python/petrinaut-optimization workspace:* UnknownUnknown
pip/packaging >= 26.2,< 27 UnknownUnknown
pip/tomlkit >= 0.15,< 0.16 UnknownUnknown
pip/gitpython 3.1.50 🟢 7.2
Details
CheckScoreReason
Maintained🟢 1030 commit(s) and 6 issue activity found in the last 90 days -- score normalized to 10
Security-Policy🟢 10security policy file detected
Dangerous-Workflow🟢 10no dangerous workflow patterns detected
Code-Review⚠️ 1Found 3/16 approved changesets -- score normalized to 1
CII-Best-Practices⚠️ 0no effort to earn an OpenSSF best practices badge detected
Binary-Artifacts🟢 10no binaries found in the repo
Packaging⚠️ -1packaging workflow not detected
Token-Permissions🟢 9detected GitHub workflow tokens with excessive permissions
Fuzzing🟢 10project is fuzzed
License🟢 10license file detected
Signed-Releases⚠️ -1no releases found
Pinned-Dependencies⚠️ 0dependency not pinned by hash detected -- score normalized to 0
Branch-Protection🟢 3branch protection is not maximal on development and all release branches
SAST🟢 10SAST tool is run on all commits
pip/alembic 1.18.5 UnknownUnknown
pip/annotated-doc 0.0.4 UnknownUnknown
pip/annotated-types 0.7.0 UnknownUnknown
pip/anyio 4.14.2 UnknownUnknown
pip/asgiref 3.12.1 🟢 4.3
Details
CheckScoreReason
Maintained🟢 1018 commit(s) and 9 issue activity found in the last 90 days -- score normalized to 10
Packaging⚠️ -1packaging workflow not detected
Code-Review🟢 5Found 14/26 approved changesets -- score normalized to 5
Binary-Artifacts🟢 10no binaries found in the repo
Token-Permissions⚠️ 0detected GitHub workflow tokens with excessive permissions
Dangerous-Workflow🟢 10no dangerous workflow patterns detected
Pinned-Dependencies⚠️ 0dependency not pinned by hash detected -- score normalized to 0
CII-Best-Practices⚠️ 0no effort to earn an OpenSSF best practices badge detected
License🟢 10license file detected
Fuzzing⚠️ 0project is not fuzzed
Signed-Releases⚠️ -1no releases found
Branch-Protection⚠️ 0branch protection not enabled on development/release branches
Security-Policy⚠️ 0security policy file not detected
SAST⚠️ 0SAST tool is not run on all commits -- score normalized to 0
pip/certifi 2026.7.22 🟢 6.4
Details
CheckScoreReason
Maintained🟢 1012 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10
Code-Review🟢 3Found 1/3 approved changesets -- score normalized to 3
Pinned-Dependencies🟢 5dependency not pinned by hash detected -- score normalized to 5
Dangerous-Workflow🟢 10no dangerous workflow patterns detected
Binary-Artifacts🟢 10no binaries found in the repo
CII-Best-Practices⚠️ 0no effort to earn an OpenSSF best practices badge detected
Security-Policy🟢 10security policy file detected
Token-Permissions🟢 10GitHub workflow tokens follow principle of least privilege
Fuzzing⚠️ 0project is not fuzzed
Signed-Releases⚠️ -1no releases found
License🟢 9license file detected
Branch-Protection⚠️ 0branch protection not enabled on development/release branches
Packaging🟢 10packaging workflow detected
SAST⚠️ 0SAST tool is not run on all commits -- score normalized to 0
pip/charset-normalizer 3.4.9 UnknownUnknown
pip/click 8.4.2 UnknownUnknown
pip/colorama 0.4.6 UnknownUnknown
pip/colorlog 6.11.0 🟢 4.9
Details
CheckScoreReason
Code-Review⚠️ 2Found 4/18 approved changesets -- score normalized to 2
Maintained🟢 1014 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10
Dangerous-Workflow🟢 10no dangerous workflow patterns detected
Binary-Artifacts🟢 10no binaries found in the repo
Token-Permissions⚠️ 0detected GitHub workflow tokens with excessive permissions
Pinned-Dependencies⚠️ 0dependency not pinned by hash detected -- score normalized to 0
CII-Best-Practices⚠️ 0no effort to earn an OpenSSF best practices badge detected
Security-Policy⚠️ 0security policy file not detected
Fuzzing⚠️ 0project is not fuzzed
License🟢 10license file detected
Signed-Releases⚠️ -1no releases found
Packaging🟢 10packaging workflow detected
Branch-Protection⚠️ -1internal error: error during branchesHandler.setup: internal error: some github tokens can't read classic branch protection rules: https://github.com/ossf/scorecard-action/blob/main/docs/authentication/fine-grained-auth-token.md
SAST⚠️ 0SAST tool is not run on all commits -- score normalized to 0
pip/fastapi 0.139.2 UnknownUnknown
pip/gitdb 4.0.12 🟢 6.8
Details
CheckScoreReason
Code-Review🟢 6Found 3/5 approved changesets -- score normalized to 6
Packaging⚠️ -1packaging workflow not detected
Security-Policy🟢 9security policy file detected
Dangerous-Workflow🟢 10no dangerous workflow patterns detected
Maintained🟢 79 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 7
Token-Permissions🟢 10GitHub workflow tokens follow principle of least privilege
Pinned-Dependencies⚠️ 0dependency not pinned by hash detected -- score normalized to 0
Binary-Artifacts🟢 10no binaries found in the repo
CII-Best-Practices⚠️ 0no effort to earn an OpenSSF best practices badge detected
Fuzzing🟢 10project is fuzzed
License🟢 9license file detected
Signed-Releases⚠️ -1no releases found
Branch-Protection⚠️ 0branch protection not enabled on development/release branches
SAST🟢 6SAST tool is not run on all commits -- score normalized to 6
pip/googleapis-common-protos 1.75.0 UnknownUnknown
pip/greenlet 3.5.3 UnknownUnknown
pip/grpcio 1.82.1 UnknownUnknown
pip/h11 0.16.0 🟢 4.4
Details
CheckScoreReason
Maintained⚠️ 00 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0
Packaging⚠️ -1packaging workflow not detected
Dangerous-Workflow🟢 10no dangerous workflow patterns detected
Code-Review🟢 5Found 9/18 approved changesets -- score normalized to 5
Binary-Artifacts🟢 10no binaries found in the repo
Token-Permissions⚠️ 0detected GitHub workflow tokens with excessive permissions
Pinned-Dependencies⚠️ 0dependency not pinned by hash detected -- score normalized to 0
CII-Best-Practices⚠️ 0no effort to earn an OpenSSF best practices badge detected
Security-Policy⚠️ 0security policy file not detected
Fuzzing🟢 10project is fuzzed
License🟢 10license file detected
Signed-Releases⚠️ -1no releases found
Branch-Protection⚠️ -1internal error: error during branchesHandler.setup: internal error: some github tokens can't read classic branch protection rules: https://github.com/ossf/scorecard-action/blob/main/docs/authentication/fine-grained-auth-token.md
SAST⚠️ 0SAST tool is not run on all commits -- score normalized to 0
pip/httpcore2 2.7.0 UnknownUnknown
pip/httptools 0.8.0 UnknownUnknown
pip/httpx2 2.7.0 UnknownUnknown
pip/idna 3.18 UnknownUnknown
pip/iniconfig 2.3.0 UnknownUnknown
pip/mako 1.3.12 UnknownUnknown
pip/markdown-it-py 4.2.0 UnknownUnknown
pip/markupsafe 3.0.3 UnknownUnknown
pip/mdurl 0.1.2 UnknownUnknown
pip/networkx 3.6.1 UnknownUnknown
pip/numpy 2.5.1 UnknownUnknown
pip/opentelemetry-api 1.44.0 UnknownUnknown
pip/opentelemetry-exporter-otlp-proto-common 1.44.0 UnknownUnknown
pip/opentelemetry-exporter-otlp-proto-grpc 1.44.0 UnknownUnknown
pip/opentelemetry-exporter-otlp-proto-http 1.44.0 UnknownUnknown
pip/opentelemetry-instrumentation 0.65b0 UnknownUnknown
pip/opentelemetry-instrumentation-asgi 0.65b0 UnknownUnknown
pip/opentelemetry-instrumentation-fastapi 0.65b0 UnknownUnknown
pip/opentelemetry-proto 1.44.0 UnknownUnknown
pip/opentelemetry-sdk 1.44.0 UnknownUnknown
pip/opentelemetry-semantic-conventions 0.65b0 UnknownUnknown
pip/opentelemetry-util-http 0.65b0 UnknownUnknown
pip/optuna 4.9.0 UnknownUnknown
pip/packaging 26.2 UnknownUnknown
pip/pluggy 1.6.0 UnknownUnknown
pip/prompt-toolkit 3.0.52 UnknownUnknown
pip/protobuf 7.35.1 UnknownUnknown
pip/pydantic 2.13.4 UnknownUnknown
pip/pydantic-core 2.46.4 🟢 6.9
Details
CheckScoreReason
Code-Review🟢 6Found 16/23 approved changesets -- score normalized to 6
Maintained🟢 1030 commit(s) and 15 issue activity found in the last 90 days -- score normalized to 10
Dangerous-Workflow🟢 10no dangerous workflow patterns detected
CII-Best-Practices⚠️ 0no effort to earn an OpenSSF best practices badge detected
Binary-Artifacts🟢 10no binaries found in the repo
Token-Permissions⚠️ 0detected GitHub workflow tokens with excessive permissions
License🟢 10license file detected
Pinned-Dependencies🟢 8dependency not pinned by hash detected -- score normalized to 8
Fuzzing🟢 10project is fuzzed
Branch-Protection🟢 3branch protection is not maximal on development and all release branches
Security-Policy🟢 10security policy file detected
Signed-Releases⚠️ -1no releases found
Packaging🟢 10packaging workflow detected
SAST⚠️ 0SAST tool is not run on all commits -- score normalized to 0
pip/pydot 4.0.1 UnknownUnknown
pip/pygments 2.20.0 UnknownUnknown
pip/pyparsing 3.3.2 UnknownUnknown
pip/pytest 9.1.1 UnknownUnknown
pip/python-dotenv 1.2.2 UnknownUnknown
pip/pyyaml 6.0.3 UnknownUnknown
pip/requests 2.34.2 UnknownUnknown
pip/rich 15.0.0 UnknownUnknown
pip/ruff 0.15.21 UnknownUnknown
pip/smmap 5.0.3 UnknownUnknown
pip/sqlalchemy 2.0.51 UnknownUnknown
pip/starlette 1.3.1 UnknownUnknown
pip/tach 0.35.0 UnknownUnknown
pip/tomli 2.4.1 UnknownUnknown
pip/tomli-w 1.2.0 UnknownUnknown
pip/tomlkit 0.15.0 UnknownUnknown
pip/tqdm 4.69.0 UnknownUnknown
pip/truststore 0.10.4 UnknownUnknown
pip/ty 0.0.58 UnknownUnknown
pip/typing-extensions 4.16.0 UnknownUnknown
pip/typing-inspection 0.4.2 UnknownUnknown
pip/urllib3 2.7.0 UnknownUnknown
pip/uvicorn 0.51.0 UnknownUnknown
pip/uvloop 0.22.1 UnknownUnknown
pip/watchfiles 1.2.0 🟢 4
Details
CheckScoreReason
Maintained🟢 57 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 5
Binary-Artifacts🟢 10no binaries found in the repo
Dangerous-Workflow🟢 10no dangerous workflow patterns detected
Code-Review🟢 3Found 9/26 approved changesets -- score normalized to 3
Token-Permissions⚠️ 0detected GitHub workflow tokens with excessive permissions
Packaging⚠️ -1packaging workflow not detected
CII-Best-Practices⚠️ 0no effort to earn an OpenSSF best practices badge detected
Pinned-Dependencies⚠️ 0dependency not pinned by hash detected -- score normalized to 0
Security-Policy⚠️ 0security policy file not detected
Fuzzing⚠️ 0project is not fuzzed
License🟢 10license file detected
Branch-Protection⚠️ -1internal error: error during branchesHandler.setup: internal error: some github tokens can't read classic branch protection rules: https://github.com/ossf/scorecard-action/blob/main/docs/authentication/fine-grained-auth-token.md
Signed-Releases⚠️ -1no releases found
SAST⚠️ 0SAST tool is not run on all commits -- score normalized to 0
pip/wcwidth 0.8.2 UnknownUnknown
pip/websockets 16.1.1 UnknownUnknown
pip/wrapt 2.2.2 UnknownUnknown
npm/@python/hash-repo-chores@workspace:libs/ 0.0.0-use.local UnknownUnknown

Scanned Files

  • apps/petrinaut-opt/uv.lock
  • libs/@local/petrinaut-optimizer-client/package.json
  • libs/@local/repo-chores/python/pyproject.toml
  • uv.lock
  • yarn.lock

@cursor cursor 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.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

There are 2 total unresolved issues (including 1 from previous review).

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Want reviews to match your repository better? Bugbot Learning can learn team-specific rules from PR activity. A team admin can enable Learning in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit ebb40a5. Configure here.

description = "Scenario-parameter optimization for Petrinaut using Optuna"
readme = "README.md"
requires-python = ">=3.10.20"
requires-python = ">=3.14,<3.15"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Docker build breaks after workspace move

High Severity

Raising requires-python to >=3.14,&lt;3.15 and moving the lockfile to the repo-root uv.lock leaves apps/petrinaut-opt/docker/Dockerfile inconsistent: it still uses Python 3.13, uv 0.11.18, and COPYs the removed package-local uv.lock. Deploy builds that use this Dockerfile will fail at the dependency layer.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit ebb40a5. Configure here.

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

Labels

area/apps area/deps Relates to third-party dependencies (area) area/infra Relates to version control, CI, CD or IaC (area) area/libs Relates to first-party libraries/crates/packages (area) area/tests New or updated tests type/eng > backend Owned by the @backend team type/eng > frontend Owned by the @frontend team type/legal Owned by the @legal team

Development

Successfully merging this pull request may close these issues.

4 participants