Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
fe84bae
PR1: ecosystem abstraction (EVM + Solana front-half)
ericeil Jul 23, 2026
93320ca
pipeline: type PreparedSystem.main via a Main generic instead of Any
ericeil Jul 23, 2026
6815140
pipeline: type _batch_cache_key via a result-type witness (drop Any)
ericeil Jul 23, 2026
71a0773
pipeline: document why run_pipeline's ecosystem type is erased to Any
ericeil Jul 23, 2026
37302e4
ecosystem: drop the dead per-property fan-out (property_unit)
ericeil Jul 23, 2026
4e0a154
ecosystem: select extraction mode by callable, drop the redundant boo…
ericeil Jul 23, 2026
0f441b2
ecosystem: unify extraction into one units() path (drop extraction_unit)
ericeil Jul 23, 2026
5c61dbd
Remove unneeded comment
ericeil Jul 23, 2026
7d36604
Comment tweaks
ericeil Jul 23, 2026
29c2a9f
Comment tweaks
ericeil Jul 23, 2026
530ed48
tweaks
ericeil Jul 23, 2026
a259e01
system_model: drop @runtime_checkable, strengthen unit tag/json dicts
ericeil Jul 23, 2026
a2058eb
docs: bring ARCHITECTURE.md up to date with the ecosystem seam
ericeil Jul 23, 2026
6add7a1
docs/ecosystem: rewrite as description-of-what-is; fix misplaced Rust…
ericeil Jul 23, 2026
f15c8ae
docs: move application-abstraction.md out of the ecosystem PR
ericeil Jul 23, 2026
60b2411
tests: golden snapshots of front-half prompt templates
ericeil Jul 23, 2026
24cd987
templates: factor shared prompt boilerplate into shared/ partials
ericeil Jul 23, 2026
97dc97f
tests: remove prompt-snapshot golden test
ericeil Jul 24, 2026
350b4f2
tests: unit-test the null Solana backend
ericeil Jul 24, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
316 changes: 316 additions & 0 deletions ARCHITECTURE.md

Large diffs are not rendered by default.

29 changes: 29 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Repository conventions for coding agents

Guidance for AI coding agents (and humans) working in this repo. Keep changes consistent
with these unless a maintainer says otherwise.

## Python

### Do NOT use `from __future__ import annotations`

Never add `from __future__ import annotations` to a module. If you touch a file that has it
and it's reasonable to do so, remove it.

Why:
- It's a dead-end feature. PEP 563 (the string-annotations behaviour this import enables) was
never made the default and has effectively been superseded by PEP 649 / PEP 749 (lazy
evaluation) from Python 3.14 on. Relying on the `__future__` behaviour is betting on a path
the language is moving away from — it will change/break under you in future versions.
- It doesn't actually solve the problem it's reached for. Stringizing *all* annotations breaks
anything that introspects them at runtime — pydantic, dataclasses, `typing.get_type_hints`,
and our own annotation-driven graph wiring (see `composer/rustapp/_llm_agent.py`, which had
to stay eager precisely because stringized `NotRequired[T]` broke pydantic unwrapping). It
trades one set of problems for a subtler set.

What to do instead (we target Python 3.12+):
- Modern syntax works at runtime without the future import: `X | None`, `list[str]`,
`dict[str, int]`, `tuple[int, ...]`, PEP 695 generics (`class Foo[T]:` / `def f[T]()`).
- For a genuine forward reference (a name not yet defined where the annotation is evaluated —
e.g. a dataclass field typed as a class defined later in the file), quote just that one
annotation: `backend: "RustBackend"`. Quote the specific ref; don't stringize the whole module.
10 changes: 5 additions & 5 deletions composer/foundry/pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@
system (a uint256 being non-negative, etc.) are also uninteresting.
"""
from composer.spec.system_model import (
ContractComponentInstance, SourceApplication,
ContractComponentInstance, ContractInstance, SourceApplication,
)

from composer.io.multi_job import HandlerFactory
Expand Down Expand Up @@ -106,7 +106,7 @@ class FoundryPhase(enum.Enum):
TEST_GENERATION = "test_generation"
REPORT = "report"

class FoundryFormalizer(Formalizer[GeneratedFoundryTest]):
class FoundryFormalizer(Formalizer[GeneratedFoundryTest, ContractComponentInstance]):
def __init__(self, conf: _ForgeRunConfig):
super().__init__(GeneratedFoundryTest, "foundry")
self.conf = conf
Expand Down Expand Up @@ -138,11 +138,11 @@ async def fetch_verdicts(self, inp: ReportComponentInput[GeneratedFoundryTest])
return await _foundry_verdicts(inp)

@dataclass
class FoundrySystem(PreparedSystem[GeneratedFoundryTest]):
class FoundrySystem(PreparedSystem[GeneratedFoundryTest, ContractComponentInstance, ContractInstance]):
form: FoundryFormalizer

@override
async def prepare_formalization(self, run: PipelineRun) -> Formalizer[GeneratedFoundryTest]:
async def prepare_formalization(self, run: PipelineRun) -> Formalizer[GeneratedFoundryTest, ContractComponentInstance]:
return self.form

@dataclass
Expand All @@ -166,7 +166,7 @@ async def prepare_system(
self,
analyzed: SourceApplication,
run: PipelineRun[FoundryPhase, None]
) -> PreparedSystem[GeneratedFoundryTest]:
) -> PreparedSystem[GeneratedFoundryTest, ContractComponentInstance, ContractInstance]:
return FoundrySystem(
main_instance(
analyzed, run.source
Expand Down
9 changes: 5 additions & 4 deletions composer/pipeline/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
CorePipelineResult
)
from composer.spec.artifacts import ArtifactIdentifier
from composer.spec.system_model import FeatureUnit
from composer.spec.service_host import ModelProvider
from composer.spec.system_analysis import SolidityIdentifier
from .core import PipelineBackend, run_pipeline
Expand Down Expand Up @@ -113,10 +114,10 @@ class StagedPipeline:
root_key: str

class Continuation[P: enum.Enum, H](Protocol):
async def __call__[FormT: BackendResult, A: ArtifactIdentifier](
async def __call__[FormT: BackendResult, A: ArtifactIdentifier, U: FeatureUnit, Main](
self,
env: ServiceHost,
backend: PipelineBackend[P, FormT, H, A]
backend: PipelineBackend[P, FormT, H, A, U, Main]
) -> CorePipelineResult[FormT]:
...

Expand Down Expand Up @@ -249,9 +250,9 @@ async def cli_pipeline[P: enum.Enum, H](
relative_path=init_source.relative_path
)

async def cont[FormT: BackendResult, A: ArtifactIdentifier](
async def cont[FormT: BackendResult, A: ArtifactIdentifier, U: FeatureUnit, Main](
env: ServiceHost,
backend: PipelineBackend[P, FormT, H, A]
backend: PipelineBackend[P, FormT, H, A, U, Main]
) -> CorePipelineResult[FormT]:
full_ctx = WorkflowContext.create(
services=conns.memory,
Expand Down
Loading
Loading