Keyboard shortcuts

Press or to navigate between chapters

Press ⌘K or Ctrl+K to search

Press ? to show this help

Press Esc to hide this help

Appendix E: Repository Structure & Implementation Plan

Repository Layout

strato/                              # Monorepo root
├── Cargo.toml                       # Rust workspace definition
├── Cargo.lock
├── pyproject.toml                   # Python annotations package ("strato")
├── LICENSE
├── README.md
│
├── crates/
│   ├── strato_ty_adapter/           # Facade over vendored Ruff/ty
│   │   ├── Cargo.toml
│   │   └── src/
│   │       ├── lib.rs
│   │       ├── project.rs           # Owns ty_project::ProjectDatabase setup
│   │       ├── facade.rs            # Stable Strato semantic query API
│   │       ├── targets.rs           # ResolvedTarget, DefinitionKey, CallableInfo
│   │       └── patches.rs           # Compile-time assertions for vendored patch APIs
│   │
│   ├── strato_core/                 # Core analysis library
│   │   ├── Cargo.toml
│   │   └── src/
│   │       ├── lib.rs
│   │       ├── discovery.rs         # Phase 1: file discovery, config loading
│   │       ├── parser.rs            # Phase 2: syntax extraction from Ruff parsed modules
│   │       ├── semantics.rs         # Phase 3: normalized facts from strato_ty_adapter
│   │       ├── graph.rs             # Phase 4: call graph data structures
│   │       ├── graph_builder.rs     # Phase 4: call graph construction
│   │       ├── annotator.rs         # Phase 5: blocking annotation
│   │       ├── propagator.rs        # Phase 6: blocking propagation (SCC)
│   │       ├── reporter.rs          # Phase 7: diagnostic generation
│   │       ├── types.rs             # Shared types
│   │       └── database/
│   │           ├── mod.rs           # BlockingDatabase
│   │           ├── stdlib.rs        # Built-in stdlib entries
│   │           ├── network.rs       # Built-in network lib entries
│   │           ├── database.rs      # Built-in database lib entries
│   │           └── subprocess.rs    # Built-in subprocess entries
│   │
│   ├── strato_cache/                # Caching subsystem
│   │   ├── Cargo.toml
│   │   └── src/
│   │       ├── lib.rs
│   │       ├── manifest.rs          # Cache manifest (content hashes)
│   │       ├── storage.rs           # Cache read/write operations
│   │       └── invalidation.rs      # Cache invalidation logic
│   │
│   └── strato_cli/                  # CLI binary
│       ├── Cargo.toml
│       ├── pyproject.toml           # PyPI "strato-cli" package (maturin)
│       └── src/
│           ├── main.rs              # Entry point
│           ├── args.rs              # CLI argument parsing (clap)
│           ├── output/
│           │   ├── mod.rs
│           │   ├── text.rs          # Text output formatter
│           │   ├── json.rs          # JSON output formatter
│           │   └── sarif.rs         # SARIF output formatter
│           └── config.rs            # pyproject.toml config parsing
│
├── vendor/
│   ├── ruff-strato-patches.md        # Patch ledger: rationale, upstreamability, tests
│   └── ruff/                         # Pinned Ruff monorepo submodule with Strato patches
│       └── crates/
│           ├── ruff_db/
│           ├── ruff_python_ast/
│           ├── ruff_python_parser/
│           ├── ty_project/
│           ├── ty_module_resolver/
│           ├── ty_python_core/
│           └── ty_python_semantic/
│
├── python/                          # Python annotations package
│   └── strato/
│       ├── __init__.py
│       ├── _annotations.py          # @blocking, @non_blocking, @unblocker
│       └── py.typed                 # PEP 561 marker
│
├── tests/
│   ├── fixtures/                    # Test Python projects
│   │   ├── a01_direct_blocking/     # A1: direct call in async
│   │   │   ├── fixture.toml         # Explicit runs, config source, assertion scope
│   │   │   ├── main.py              # Fixture source
│   │   │   └── expected.json        # Expected JSON used by manifest runs
│   │   ├── a02_transitive_blocking/ # A2: transitive blocking
│   │   ├── a03_executor_safe/       # A3: run_in_executor
│   │   ├── a04_to_thread_safe/      # A4: asyncio.to_thread
│   │   ├── a05_sync_only_safe/      # A5: sync standalone
│   │   ├── a06_blocking_annotation/ # A6: @blocking decorator
│   │   ├── a07_non_blocking_override/ # A7: @non_blocking
│   │   ├── a08_property_blocking/   # A8: @property
│   │   ├── a09_dunder_blocking/     # A9: dunder methods
│   │   ├── a10_cross_file/          # A10: blocking across files
│   │   ├── a11_deep_transitive/     # A11: deep call chain
│   │   ├── a12_multiple_callers/    # A12: multiple async callers
│   │   ├── a13_mixed_safe_unsafe/   # A13: mixed safe/unsafe
│   │   ├── a14_unblocker_basic/     # A14: @unblocker
│   │   ├── a15_executor_wrapper_config/ # A15: configured wrappers
│   │   ├── a16_intermediate_property/ # A16: intermediate property classification
│   │   ├── a17_intermediate_dunder/  # A17: intermediate dunder classification
│   │   ├── a18_non_blocking_scc/     # A18: SCC + @non_blocking
│   │   ├── a19_alias_wrapper/       # A19: alias-based wrapper
│   │   ├── a20_deterministic_ordering/ # A20: deterministic ordering
│   │   ├── a21_cache_parity/        # A21: fresh/cached parity
│   │   ├── a22_star_import/         # A22: star import
│   │   ├── a23_namespace_package/   # A23: namespace package
│   │   ├── a24_related_locations/   # A24: related locations
│   │   ├── a25_syntax_warnings/     # A25: syntax warnings
│   │   ├── a26_stub_annotation/     # A26: .pyi blocking annotation
│   │   ├── a27_blocking_config_add/ # A27: blocking.add config
│   │   ├── a28_blocking_config_remove/ # A28: blocking.remove config
│   │   ├── a29_blocking_module_prefix/ # A29: blocking_modules config
│   │   ├── a30_python_version_to_thread/ # A30: python-version escape hatch
│   │   ├── a31_unresolved_call_precision/ # A31: unknown calls skipped
│   │   ├── a32_partial_executor_wrapper/ # A32: functools.partial executor wrapper
│   │   ├── a33_method_call_resolution/ # A33: instance/static/class methods
│   │   ├── a34_callable_object_dunder/ # A34: callable object __call__
│   │   ├── a35_dunder_operations/      # A35: representative STRATO004 operations
│   │   ├── a36_deterministic_ordering_repeat/ # A36: deterministic repeat run
│   │   ├── a37_cache_parity_cached/    # A37: cached parity run
│   │   ├── a38_blocking_config_add_configured/ # A38: configured blocking.add
│   │   └── a39_blocking_config_remove_configured/ # A39: configured blocking.remove
│   ├── integration/                 # Rust integration tests
│   │   ├── harness.rs               # Shared test harness
│   │   ├── test_direct_blocking.rs
│   │   ├── test_indirect_blocking.rs
│   │   ├── test_executor.rs
│   │   ├── test_annotations.rs
│   │   ├── test_property.rs
│   │   ├── test_dunder.rs
│   │   ├── test_cross_file.rs
│   │   ├── test_output_formats.rs
│   │   └── test_performance.rs
│   └── unit/
│
├── stubs/                           # Example .pyi stubs
│   └── examples/
│       └── redis.pyi
│
└── docs/
    └── rules/
        ├── STRATO001.md
        ├── STRATO002.md
        ├── STRATO003.md
        └── STRATO004.md

Cargo Workspace

Workspace Members:

CratePurposeDependencies
strato_ty_adapterStable facade over vendored Ruff/ty project, parser, resolver, and semantic APIsruff_db, ruff_python_ast, ty_project, ty_module_resolver, ty_python_core, ty_python_semantic via vendor/ruff paths
strato_coreCore analysis library (7-phase pipeline)strato_ty_adapter, petgraph, serde, rayon, thiserror
strato_cacheIncremental caching subsystemserde, bincode, sha2
strato_cliCLI binary and output formattersstrato_core, strato_cache, clap, miette, serde_json, toml, globset

Vendored Ruff/ty Dependencies:

DependencyVersion/SourcePurpose
vendor/ruffGit submodule pinned to an audited Ruff commitSource for Ruff parser, AST, database, and ty crates
ruff_dbPath dependency from vendor/ruff/crates/ruff_dbSource text, file IDs, parsed modules, Salsa database traits
ruff_python_parserPath dependency from vendor/ruff/crates/ruff_python_parserPython parser used by ruff_db::parsed_module
ruff_python_astPath dependency from vendor/ruff/crates/ruff_python_astPython AST types and visitors
ty_projectPath dependency from vendor/ruff/crates/ty_projectProject discovery/indexing and ProjectDatabase
ty_module_resolverPath dependency from vendor/ruff/crates/ty_module_resolverModule/search-path resolution
ty_python_corePath dependency from vendor/ruff/crates/ty_python_coreCore semantic IDs, definitions, scopes, and program state
ty_python_semanticPath dependency from vendor/ruff/crates/ty_python_semantic, patched if neededType/name/attribute/call semantic facts

The crate list above identifies key consumed crates, not a partial checkout. Strato vendors the entire Ruff monorepo because these crates depend on additional internal Ruff/ty crates such as ty_vendored, ty_static, ty_combine, ty_site_packages, and other workspace members.

Other External Dependencies:

DependencyVersion/SourcePurpose
petgraph0.6Call graph data structure
serde1 (derive)Serialization
bincode1Binary cache format
clap4 (derive)CLI argument parsing
rayon1Parallel file processing
sha20.10File content hashing
miette7 (fancy)Beautiful error output

Implementation Milestones

MilestoneNameKey DeliverableEffort
M-2Vendor Ruff BaselineAdd pinned vendor/ruff submodule, path dependencies, patch ledger, and documented upgrade procedureMedium
M-1Facade + Patch SpikeImplement strato_ty_adapter, add surgical vendored Ruff/ty APIs for all required semantic facts, and prove all facade queries on fixturesLarge
M0Project ScaffoldingCompiling workspace with stub modules and vendored Ruff/ty path dependenciesSmall
M1Parser + DiscoveryIndex project via ty_project, load Ruff parsed modules for .py and .pyi, extract FileSyntax, and load the effective blocking database before graph constructionMedium
M2Semantic LayerFacade-backed module/name/type/call/property/dunder facts normalized for StratoLarge
M3Call GraphProject-wide call graph constructionLarge
M4Blocking Database61 known blocking functions with help textMedium
M5PropagationSCC-based blocking propagation (Tarjan’s algorithm)Medium
M6Escape Hatchesrun_in_executor, to_thread, @unblocker detectionSmall
M7Properties + DundersImplicit call detection (@property, __str__, etc.)Medium
M8DiagnosticsError reporting with intervention strategiesMedium
M9CLI + OutputWorking binary with text/JSON/SARIF outputMedium
M10CachingIncremental analysis with content-based invalidationMedium
M11Integration TestsAll 25 acceptance test fixtures passMedium
M12Performance + PolishPerformance validated, README, maturin buildMedium

Critical Path: M-2 -> M-1 -> M0 -> M1 -> M2 -> M3 -> M4 -> M5 -> M6 -> M7 -> M8 -> M9 -> M10 -> M11 -> M12 (strictly sequential)

Vendored Ruff Patch Policy

Ruff/ty patches are allowed, but must stay narrow and auditable.

RuleRequirement
Patch locationAll modifications live under vendor/ruff on a Strato-maintained branch or patch queue
Patch purposeExpose semantic facts needed by strato_ty_adapter; never implement Strato blocking policy in Ruff/ty
Patch ledgerEvery change is recorded in vendor/ruff-strato-patches.md with file, rationale, upstreamability, and test coverage
Facade boundaryOnly strato_ty_adapter may depend directly on Ruff/ty internals
Upgrade processUpdating Ruff requires replaying patches, running facade conformance tests, all acceptance fixtures, and determinism tests

Required patched/facade facts for v1:

FactNeeded For
definitions_for_call for ExprCall calleeDirect calls, aliases, methods, constructors, callable objects
definitions_for_callable_reference for expressions passed as valuesSynthetic in_executor=true edges and configured wrapper callable arguments
Descriptor-aware property getter target for ExprAttributeSTRATO003, returning the property.fget definition rather than only the descriptor object
definitions_for_dunder_operation for Strato’s operation enumSTRATO004 for unary, binary, comparison, conversion, formatting, subscript, iterator, context-manager, and __call__ operations
Event-loop run_in_executor target identityBuilt-in executor-wrapper detection without Strato-owned assignment heuristics
Deterministic qualified display name for DefinitionNode display, config matching, diagnostics
External qualified aliases for resolved non-first-party callsBlocking DB phantom matching across public names, re-exports, inherited definitions, and implementation modules
Parsed module access from the same ty databaseAvoid independent double parsing

Only the Ruff monorepo is vendored under vendor/ruff. Strato does not vendor the standalone ty package wrapper; all Rust path dependencies point directly at vendor/ruff/crates/....

Build & Test

# Build all crates
cargo build

# Build release binary
cargo build --release -p strato_cli

# Run all tests
cargo test

# Run performance tests
cargo test test_performance --release

# Build Python wheel (requires maturin)
maturin build -m crates/strato_cli/Cargo.toml

# Install annotations package
pip install -e .

# Run analysis
cargo run -p strato_cli -- check <path>
cargo run -p strato_cli -- check <path> --output json
cargo run -p strato_cli -- check <path> --output sarif