Skip to content

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

Open
indietyp wants to merge 10 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 10 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 Aug 4, 2026 8:16am
hashdotdesign-tokens Ready Ready Preview Aug 4, 2026 8:16am
petrinaut Ready Ready Preview Aug 4, 2026 8:16am

@cursor

cursor Bot commented Jul 15, 2026

Copy link
Copy Markdown

PR Summary

Medium Risk
Broad CI and monorepo wiring changes plus petrinaut-opt runtime/Docker and dependency upgrades; incorrect prune or lock handling could break builds, but scope is mostly tooling and one service.

Overview
Introduces a root uv workspace (Python 3.14, shared uv.lock, ruff/ty/tach/pytest) and hash-repo-chores with sync, lint, and prune so membership, bounded deps, generated @python/* package.json wiring, and turbo-prune stubs stay enforced in CI.

Developer and CI wiring: new mise tasks lint:python, fix:python, and sync:python; root yarn lint:python / fix:python; per-package lint:ruff in the lint workflow; lefthook ruff on staged .py files; prune action moved to libs/@local/repo-chores/python/repo_chores/prune.py and now copies pyproject.toml / uv.lock. uv is bumped to 0.11.28.

petrinaut-opt joins the workspace as @python/petrinaut-optimization (turbo package-based deploy instead of path filters), Docker installs via root lock + --package petrinaut-optimization, Python 3.14, tighter deps, and refactors (Pydantic types, shared SSE admission, OpenAPI JsonValue + contract tests). Docs updated in README.md and AGENTS.md.

Reviewed by Cursor Bugbot for commit 479113a. 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.

@vercel
vercel Bot temporarily deployed to Preview – hashdotdesign-tokens July 15, 2026 21:50 Inactive
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
@vercel
vercel Bot temporarily deployed to Preview – petrinaut July 15, 2026 21:57 Inactive
@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.

@vercel
vercel Bot temporarily deployed to Preview – hashdotdesign-tokens July 15, 2026 22:17 Inactive
Comment thread pyproject.toml Outdated
Comment thread pyproject.toml Fixed

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 Outdated
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

github-actions Bot commented Jul 27, 2026

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
  • ⚠️ 32 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
GitPython: Unguarded git option forwarding in IndexFile.checkout() and TagReference.create() enables arbitrary file overwrite and arbitrary file readhigh3.1.57
GitPython: Incomplete unsafe_git_archive_options denylist omits --add-file / --add-virtual-file, enabling arbitrary file read via Repo.archive()moderate3.1.57
GitPython: Arbitrary file truncation via git rev-list --output argument injection in unguarded Commit.countmoderate3.1.56

License Issues

apps/petrinaut-opt/package.json

PackageVersionLicenseIssue Type
@hashintel/petrinaut-cliworkspace:*NullUnknown License

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
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
tach0.35.0NullUnknown License
tomlkit0.15.0NullUnknown License
tqdm4.69.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/@hashintel/petrinaut-cli workspace:* UnknownUnknown
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.5
Details
CheckScoreReason
Code-Review🟢 4Found 5/12 approved changesets -- score normalized to 4
Security-Policy🟢 10security policy file detected
Maintained🟢 1030 commit(s) and 9 issue activity found in the last 90 days -- score normalized to 10
Dangerous-Workflow🟢 10no dangerous workflow patterns detected
Packaging⚠️ -1packaging workflow not detected
CII-Best-Practices⚠️ 0no effort to earn an OpenSSF best practices badge detected
Binary-Artifacts🟢 10no binaries found in the repo
Token-Permissions🟢 9detected GitHub workflow tokens with excessive permissions
Fuzzing🟢 10project is fuzzed
License🟢 10license file detected
Pinned-Dependencies⚠️ 0dependency not pinned by hash detected -- score normalized to 0
Signed-Releases⚠️ -1no releases found
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
Code-Review🟢 5Found 14/26 approved changesets -- score normalized to 5
Dangerous-Workflow🟢 10no dangerous workflow patterns detected
Maintained🟢 1018 commit(s) and 9 issue activity found in the last 90 days -- score normalized to 10
Token-Permissions⚠️ 0detected GitHub workflow tokens with excessive permissions
Binary-Artifacts🟢 10no binaries found in the repo
Packaging⚠️ -1packaging workflow not 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
Fuzzing⚠️ 0project is not fuzzed
License🟢 10license file detected
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
Binary-Artifacts🟢 10no binaries found in the repo
Maintained🟢 1013 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
Security-Policy🟢 10security policy file detected
Token-Permissions🟢 10GitHub workflow tokens follow principle of least privilege
Dangerous-Workflow🟢 10no dangerous workflow patterns detected
Pinned-Dependencies🟢 5dependency not pinned by hash detected -- score normalized to 5
CII-Best-Practices⚠️ 0no effort to earn an OpenSSF best practices badge detected
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 5/18 approved changesets -- score normalized to 2
Dangerous-Workflow🟢 10no dangerous workflow patterns detected
Binary-Artifacts🟢 10no binaries found in the repo
Maintained🟢 1016 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10
Pinned-Dependencies⚠️ 0dependency not pinned by hash detected -- score normalized to 0
Token-Permissions⚠️ 0detected GitHub workflow tokens with excessive permissions
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
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
Packaging🟢 10packaging workflow detected
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.1
Details
CheckScoreReason
Maintained⚠️ 0project is archived
Code-Review🟢 6Found 3/5 approved changesets -- score normalized to 6
Packaging⚠️ -1packaging workflow not detected
Security-Policy🟢 9security policy file detected
Binary-Artifacts🟢 10no binaries found in the repo
Dangerous-Workflow🟢 10no dangerous workflow patterns detected
Token-Permissions🟢 10GitHub workflow tokens follow principle of least privilege
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
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
Code-Review🟢 5Found 9/18 approved changesets -- score normalized to 5
Packaging⚠️ -1packaging workflow not detected
Dangerous-Workflow🟢 10no dangerous workflow patterns detected
Token-Permissions⚠️ 0detected GitHub workflow tokens with excessive permissions
Maintained⚠️ 00 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0
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
Security-Policy⚠️ 0security policy file not detected
License🟢 10license file detected
Fuzzing🟢 10project is fuzzed
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 🟢 7
Details
CheckScoreReason
Code-Review🟢 7Found 22/28 approved changesets -- score normalized to 7
Maintained🟢 1030 commit(s) and 6 issue activity found in the last 90 days -- score normalized to 10
CII-Best-Practices⚠️ 0no effort to earn an OpenSSF best practices badge detected
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🟢 8dependency not pinned by hash detected -- score normalized to 8
License🟢 10license file detected
Fuzzing🟢 10project is fuzzed
Signed-Releases⚠️ -1no releases found
Security-Policy🟢 10security policy file detected
Branch-Protection🟢 3branch protection is not maximal on development and all release branches
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
Dangerous-Workflow🟢 10no dangerous workflow patterns detected
Maintained🟢 57 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 5
Code-Review🟢 3Found 9/26 approved changesets -- score normalized to 3
CII-Best-Practices⚠️ 0no effort to earn an OpenSSF best practices badge detected
Binary-Artifacts🟢 10no binaries found in the repo
Security-Policy⚠️ 0security policy file not detected
License🟢 10license file detected
Token-Permissions⚠️ 0detected GitHub workflow tokens with excessive permissions
Pinned-Dependencies⚠️ 0dependency not pinned by hash detected -- score normalized to 0
Packaging⚠️ -1packaging workflow not detected
Fuzzing⚠️ 0project is not fuzzed
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/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/package.json
  • apps/petrinaut-opt/uv.lock
  • libs/@local/petrinaut-optimizer-client/package.json
  • libs/@local/repo-chores/python/pyproject.toml
  • uv.lock
  • yarn.lock

@vercel
vercel Bot temporarily deployed to Preview – hashdotdesign-tokens July 27, 2026 08:54 Inactive

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

Bring the petrinaut-opt Python service into the monorepo's turbo and
Python workspace tooling, add OpenAPI document validation tests, upgrade
Python/uv versions, and improve repo-chores sync and linting to support
dependency bound checking against resolved versions.
Copilot AI review requested due to automatic review settings August 4, 2026 07:57
@vercel
vercel Bot temporarily deployed to Preview – hashdotdesign-tokens August 4, 2026 07:59 Inactive
Comment thread pyproject.toml

[tool.uv]
add-bounds = "major" # require cargo-style bounded ranges (>=1.2.3, <2.0.0)
exclude-newer = "5 days" # mirrors npm release age

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Semgrep identified a blocking 🔴 issue in your code:

Dependency cooldown period set to 5 days instead of recommended 7 days, allowing resolution of potentially malicious newly-published packages.

More details about this

The exclude-newer setting in [tool.uv] is configured to only 5 days, which is shorter than the recommended 7-day dependency cooldown period. This means your build can resolve package versions published less than 7 days ago, including newly released versions that may be malicious, unstable, or have undiscovered vulnerabilities.

Exploit scenario: An attacker could publish a malicious version of a popular dependency on day 1, then wait 5 days. When your CI/CD pipeline runs after day 5, uv will resolve and include this malicious package version in your build, potentially injecting backdoors or data exfiltration code into your application and all downstream consumers.

The problematic line is exclude-newer = "5 days" which falls short of the 7-day safety threshold.

To resolve this comment:

✨ Commit fix suggestion

Suggested change
exclude-newer = "5 days" # mirrors npm release age
# Root of the Python workspace. Shared configuration for every Python package
# in the repository lives here; per-package manifests only declare identity and
# dependencies. Generated sections are kept correct by `mise run sync:python`
# (see libs/@local/repo-chores/python) and validated in CI.
[project]
description = "Workspace-level Python configuration for the HASH monorepo"
name = "hash"
version = "0.0.0"
# The single source of truth for the workspace Python version: every member
# must declare exactly the same bound, enforced by `repo-chores sync --check`.
requires-python = ">=3.14,<3.15"
[tool.uv]
add-bounds = "major" # require cargo-style bounded ranges (>=1.2.3, <2.0.0)
exclude-newer = "7 days" # mirrors npm release age
package = false
[tool.uv.workspace]
# Managed by `mise run sync:python`
members = [
"apps/petrinaut-opt",
"libs/@local/repo-chores/python",
]
[dependency-groups]
dev = [
"hash-repo-chores", # workspace tooling
"pytest>=9.1.1,<10",
"ruff>=0.15.21,<0.16",
"tach>=0.35,<0.36",
"ty>=0.0.58,<0.1",
]
[tool.uv.sources]
hash-repo-chores = { workspace = true }
[tool.pytest.ini_options]
addopts = "-q --import-mode=importlib"
# Managed by `mise run sync:python`
testpaths = [
"apps/petrinaut-opt/tests",
"libs/@local/repo-chores/python/tests",
]
# Managed by `mise run sync:python`. A member's tests import its modules by the
# names its own directory exposes, the way its own pytest configuration does, so
View step-by-step instructions
  1. Update the exclude-newer value under [tool.uv] from 5 days to at least 7 days.
    For example, change it to exclude-newer = "7 days".

  2. Keep the setting in the [tool.uv] section so uv applies the cooldown during dependency resolution.
    This makes uv avoid package releases newer than the configured age.

  3. If you want a longer buffer, use a larger valid duration such as exclude-newer = "14 days", but do not keep it below 7 days.

💬 Ignore this finding

Reply with Semgrep commands to ignore this finding.

  • /fp <comment> for false positive
  • /ar <comment> for acceptable risk
  • /other <comment> for all other reasons

Alternatively, triage in Semgrep AppSec Platform to ignore the finding created by uv-missing-dependency-cooldown.

You can view more details about this finding in the Semgrep AppSec Platform.

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.

Pull request overview

Copilot reviewed 54 out of 59 changed files in this pull request and generated 1 comment.

Suppressed comments (1)

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

  • hatchling is an unbounded build dependency, so installing hash-repo-chores can select an arbitrary future backend release even when uv.lock is unchanged. This also bypasses the new policy: lint_workspace only checks project and dev dependencies (repo_chores/lint.py:238), while AGENTS.md states that Python dependency ranges are bounded on both sides. Add a bounded hatchling requirement and extend the dependency lint (with a regression test) to cover [build-system].requires so the invariant remains enforceable.

Comment on lines +86 to +87
COPY pyproject.toml uv.lock ./
COPY apps/petrinaut-opt/pyproject.toml apps/petrinaut-opt/pyproject.toml

@vilkinsons vilkinsons left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@indietyp Please request my review directly (on behalf of legal) when this is passing/ready

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.

5 participants