Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
110 commits
Select commit Hold shift + click to select a range
12c7ba5
checkpoint
jtoman Jun 25, 2026
d8b7536
finishing up
jtoman Jun 25, 2026
a2e2ca9
final steps
jtoman Jun 25, 2026
1018fa4
restoring prover runs
jtoman Jun 25, 2026
5252fe7
Merge branch 'master' of github.com:Certora/AutoProver into jtoman/ap…
jtoman Jun 25, 2026
53b380f
Merge branch 'master' of github.com:Certora/AutoProver into jtoman/ap…
jtoman Jun 26, 2026
77d7693
Final fixes
jtoman Jun 29, 2026
a7c165b
fix tests
jtoman Jun 29, 2026
b26db71
Nits
jtoman Jun 29, 2026
e886cc9
Some docs
ericeil Jul 7, 2026
fb2e054
Docs
ericeil Jul 7, 2026
5b1d55b
Update doc
ericeil Jul 7, 2026
9ff0c6c
More docs
ericeil Jul 7, 2026
b75cd22
Add Rust application/backend framework (PyO3)
ericeil Jul 7, 2026
bd648bc
Add generic entry point + frontend host for Rust applications
ericeil Jul 7, 2026
aba8c4d
docs: proposal for the ecosystem abstraction (EVM, Solana, Soroban)
ericeil Jul 7, 2026
1fb589c
Ecosystem abstraction phase 1: extract the Language/Chain seam (EVM)
ericeil Jul 7, 2026
5f8df5d
Ecosystem abstraction phase 2: pair backend↔ecosystem via an App type…
ericeil Jul 7, 2026
12bd9ef
Ecosystem abstraction phase 3: select the ecosystem from the Rust des…
ericeil Jul 7, 2026
1282f28
Ecosystem phase 4 (1/2): generalize driver over Unit/Main + Solana mo…
ericeil Jul 8, 2026
c24e9ff
Ecosystem phase 4 (2/2): Solana prompts + null backend + gate (passing)
ericeil Jul 8, 2026
260ad78
docs: mark ecosystem phase 4 (Solana) done in the phased plan
ericeil Jul 8, 2026
fe5669a
docs: proposal for a Solana verification application (Crucible backend)
ericeil Jul 8, 2026
cf0f056
docs: add LLM knowledge-access (RAG) plan to the Crucible proposal
ericeil Jul 8, 2026
93e0e14
rustapp: add general RunCommand effect (Crucible phase 1)
ericeil Jul 8, 2026
2668d5c
rustapp: make the adapter ecosystem-agnostic (Crucible phase 1)
ericeil Jul 8, 2026
dbef661
crucible: add the crucible-app Rust wheel skeleton (phase 1)
ericeil Jul 8, 2026
b0a457a
crucible: Solana build step + buildable solana_vault + phase-1 gate
ericeil Jul 8, 2026
15e5049
crucible: deliverable model — harness-crate ArtifactStore (phase 2)
ericeil Jul 8, 2026
0b3cb3a
rustapp: tool-enabled call_llm (Crucible phase 3, §7.5)
ericeil Jul 8, 2026
62b26ad
crucible: fixture-authoring setup session (phase 3, T2)
ericeil Jul 8, 2026
bcf700d
crucible: phase-3 fixture-authoring gate (green) + call_llm agent module
ericeil Jul 8, 2026
865418d
docs: mark Crucible phase 3 (fixture-authoring loop) done with the ga…
ericeil Jul 8, 2026
ba22672
docs: make crucible_kb RAG build + entry-point binding explicit in Ph…
ericeil Jul 8, 2026
55e6331
crucible: per-component test authoring + fuzzing + verdicts (phase 4)
ericeil Jul 8, 2026
5366d9d
docs: mark Crucible phase 4 (per-component tests + verdicts) done wit…
ericeil Jul 8, 2026
83599fa
test_scenarios/solana_vault: gitignore crucible fuzzing corpus/output…
ericeil Jul 8, 2026
0c06c6d
crucible: package the application — pipeline + CLI wiring (phase 5)
ericeil Jul 8, 2026
b5f17da
crucible: pipeline manifest pre-placement + .so build (phase 5)
ericeil Jul 8, 2026
d505da7
crucible: full-vertical end-to-end gate (phase 5, green)
ericeil Jul 8, 2026
ddf2219
docs: mark Crucible phase 5 (packaging) done with the full-vertical g…
ericeil Jul 8, 2026
104b1b4
crucible: build + populate the crucible_kb RAG (§7.5 knowledge base)
ericeil Jul 9, 2026
5eeb875
docs: mark crucible_kb RAG as built + populated (retrieval proven)
ericeil Jul 9, 2026
6e2214a
docs: design the RunCommand sandbox (Phase 6)
ericeil Jul 9, 2026
8e9abbd
sandbox: add the tool-agnostic SandboxProvider seam (Phase 6 step 1)
ericeil Jul 9, 2026
99ee6a0
sandbox: add the run-confined launcher provider (Phase 6 step 2)
ericeil Jul 9, 2026
b06d5e9
sandbox: move command runner + sandbox seam out of rustapp into compo…
ericeil Jul 9, 2026
89bfbe0
sandbox: apply the provider in run_local_command + wire it through (P…
ericeil Jul 9, 2026
1365167
sandbox: offline dependency resolution (Phase 6 step 4)
ericeil Jul 9, 2026
7ae6331
sandbox: escape gate (Part A) + legitimate-build gate (Part B build-h…
ericeil Jul 9, 2026
4424e27
sandbox: flip Crucible default to launcher; harness warm; build run-c…
ericeil Jul 9, 2026
3a1107b
crucible: harden fixture/test authoring loop against compile failures…
ericeil Jul 9, 2026
20294fd
crucible: worked-example fixture + correct crate-id + failure logging…
ericeil Jul 9, 2026
021a4dd
sandbox: grant a private TMPDIR under the workdir (linker scratch) — …
ericeil Jul 9, 2026
1555614
docs: Phase 6 e2e passes under the launcher; record the /tmp root cau…
ericeil Jul 9, 2026
2dde799
crucible: fix the shared-harness concurrency races (feature + main.rs)
ericeil Jul 9, 2026
c1cc49d
docs: e2e now delivers all 3 instructions under the launcher (concurr…
ericeil Jul 9, 2026
3a5fded
sandbox: private per-run CARGO_HOME (no shared-cache poisoning by unt…
ericeil Jul 9, 2026
16b4b78
docker: exclude **/target from build context (run-confined stage reco…
ericeil Jul 9, 2026
e880769
docs: Crucible toolchain versioning/packaging options + EVM prior art
ericeil Jul 9, 2026
7161e2d
Merge origin/master (Generic Pipeline Refactor #27) into eric/crucible
ericeil Jul 9, 2026
b4ca2f0
Fix API drift after master merge: memory tool, provider, ModelProvider
ericeil Jul 9, 2026
164fa8c
crucible: exclude in-workdir build/sandbox scratch from LLM file tools
ericeil Jul 10, 2026
66be74f
report: close ReportBackend to {prover, foundry, crucible}
ericeil Jul 10, 2026
ca79f6e
crucible: move app-specific formalization out of the generic rust ada…
ericeil Jul 10, 2026
6ecface
docs: plan for splitting eric/crucible into 4 stacked PRs
ericeil Jul 10, 2026
1689ffa
fix(pyright): clean the generic-driver / Solana type seams
ericeil Jul 10, 2026
db31979
rustapp: label the authoring turn with the app name, not "rust backend"
ericeil Jul 10, 2026
845589f
docs: human demo guide for the Crucible vault scenario
ericeil Jul 10, 2026
5862c2c
docs: Crucible→Foundry parity gap analysis
ericeil Jul 10, 2026
2c0f693
crucible: live build/fuzz telemetry + tui-crucible (parity gap #1)
ericeil Jul 10, 2026
e2e0b5e
docs: mark parity gap #1 (TUI + telemetry) done in the analysis
ericeil Jul 10, 2026
5a882de
crucible: docs-search tools degrade gracefully instead of failing the…
ericeil Jul 10, 2026
55a5959
crucible: design-doc auto-discovery when system_doc is omitted (parit…
ericeil Jul 10, 2026
9412f2a
docs: mark parity gap #2 (design-doc discovery) done
ericeil Jul 10, 2026
266f421
crucible: drop the inert --fuzz-cores/--stateful/--crucible-version f…
ericeil Jul 10, 2026
f118f09
docs: mark parity gap #3 (inert flags) done
ericeil Jul 10, 2026
236b0cd
docs: design note on Crucible unit granularity (per-instruction vs gl…
ericeil Jul 10, 2026
fd51700
crucible: whole-program invariant extraction + per-invariant fuzz units
ericeil Jul 10, 2026
2ef7ed8
docs: mark unit-granularity change implemented (per-invariant fuzz un…
ericeil Jul 10, 2026
e12e268
test: e2e gate reports invariants, not instructions (granularity change)
ericeil Jul 10, 2026
279b6d9
docs: crate-per-component parallelism investigated + deferred
ericeil Jul 11, 2026
b932bd0
rustapp: let the backend define the authoring system prompt; drop the…
ericeil Jul 11, 2026
f84a1aa
crucible: surface fuzz verdicts in the console and TUI
ericeil Jul 11, 2026
be28e6e
docs: design the service-shaped Rust backend API (replace the IoC loop)
ericeil Jul 13, 2026
164a0dd
rustapp: replace the IoC loop with a service-shaped backend API
ericeil Jul 13, 2026
4df3c86
crucible: fuse the component build gate into validate (drop per-compo…
ericeil Jul 14, 2026
96dab55
Drop `from __future__ import annotations`; document the convention
ericeil Jul 14, 2026
d7918b6
Sweep `from __future__ import annotations` from all branch-changed files
ericeil Jul 14, 2026
746c901
_llm_agent: trim the future-annotations note now that the repo bans it
ericeil Jul 14, 2026
b58de83
rustapp: drop the orphaned prover/feedback hook machinery
ericeil Jul 14, 2026
ae9d322
rustapp: merge _llm_agent into adapter.py
ericeil Jul 14, 2026
326d583
rustapp: extend the passive-backend API for pure-Rust apps (phase 1)
ericeil Jul 14, 2026
8fc86d4
docs: rust-pure-app §4 — workspace_prep is a pure plan the host executes
ericeil Jul 14, 2026
386ec6f
rustapp: generic host honors the pure-app descriptor flags (phase 2)
ericeil Jul 14, 2026
4dad07d
crucible-app: pure-Rust wheel — own crate rendering, prep, grants, pr…
ericeil Jul 14, 2026
9595aa0
crucible: delete composer/crucible/, drive the wheel via the generic …
ericeil Jul 14, 2026
55ea5f8
test: refresh stale crucible gate docstrings for the pure-app path
ericeil Jul 14, 2026
c1f2b88
rustapp: drop vestigial fuzz_timeout_s plumbing
ericeil Jul 14, 2026
61827b1
docs: make the analyzed-source vs. backend-implementation language di…
ericeil Jul 14, 2026
cd0d27e
pipeline: make the formalization core generic over the unit type (U: …
ericeil Jul 14, 2026
e399f3d
pipeline: unify the global/per-component extraction paths in _extract…
ericeil Jul 14, 2026
6a6df05
build: make the maturin wheels build automatically via `uv sync --gro…
ericeil Jul 15, 2026
37f7b88
crucible: add a reviewer/judge turn to the formalization loop
ericeil Jul 15, 2026
ccc3dd5
crucible: capture the fuzzer's counterexample into the verdict (obser…
ericeil Jul 16, 2026
17a4d4e
rustapp: run the judge in-loop as an author tool, not a separate host…
ericeil Jul 16, 2026
6a233b4
rustapp: drop code_explorer from the review sub-agent (judge cost clamp)
ericeil Jul 16, 2026
bc2dc9e
crucible: collapse to a single whole-program harness + one run
ericeil Jul 16, 2026
efb71af
crucible: ship the RAG corpus as a committed JSON manifest + generic …
ericeil Jul 16, 2026
8c73f8c
crucible: move lib.rs strings into askama .j2 templates
ericeil Jul 16, 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
4 changes: 4 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,7 @@ build/
dist/
.idea/
.vscode/

# Cargo build output — the image's sandbox-builder stage recompiles run-confined;
# copying host target/ (large) would only bloat the build context.
**/target/
284 changes: 284 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.
22 changes: 22 additions & 0 deletions composer/crucible_launch.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
"""Console entry points for the Crucible (Solana fuzzing) application.

Crucible is now a *pure-Rust app* (``docs/rust-pure-app.md``): the ``crucible_app`` wheel + its
descriptor define everything (the shared fixture, crate deliverable, workspace prep, sandbox
grants, verdict summary), so these are the same two-line shims echoprover uses — no
Crucible-specific Python package. ``import composer.bind`` runs first (inside
``composer.rustapp.cli``) for the import-time DI / test-tape bootstrap.
"""

from composer.rustapp.cli import console_main, tui_main

_MODULE = "crucible_app"


def console_crucible() -> int:
"""Run the Crucible application in console mode."""
return console_main(_MODULE)


def tui_crucible() -> int:
"""Run the Crucible application in the Textual TUI."""
return tui_main(_MODULE)
8 changes: 4 additions & 4 deletions composer/foundry/pipeline.py
Original file line number Diff line number Diff line change
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]):
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]:
return FoundrySystem(
main_instance(
analyzed, run.source
Expand Down
17 changes: 17 additions & 0 deletions composer/io/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,23 @@ def emit_custom_event(payload: Mapping[str, Any]):
raise ValueError("No IO handler installed")
curr_io[0].push(ProgressEvent(dict(payload)))


def push_custom_update(
payload: Mapping[str, Any], *, thread_id: str, checkpoint_id: str = ""
) -> bool:
"""Push a ``CustomUpdate`` to the current ``with_handler`` scope's queue so it
reaches ``EventHandler.handle_event`` — the out-of-graph analogue of
``get_stream_writer()``. Used by backends (e.g. the Rust IoC loop) that emit
domain events *between* graph calls, where ``get_stream_writer()`` is unavailable.
Returns ``False`` (event dropped) if no handler scope is installed."""
curr_io = _io_handler.get()
if curr_io is None:
return False
curr_io[0].push(
CustomUpdate(payload=dict(payload), thread_id=thread_id, checkpoint_id=checkpoint_id)
)
return True

async def run_graph[S: StateLike, C: StateLike | None, I: StateLike](
graph: CompiledStateGraph[S, C, I, Any],
ctxt: C,
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](
self,
env: ServiceHost,
backend: PipelineBackend[P, FormT, H, A]
backend: PipelineBackend[P, FormT, H, A, U]
) -> CorePipelineResult[FormT]:
...

Expand Down Expand Up @@ -248,9 +249,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](
env: ServiceHost,
backend: PipelineBackend[P, FormT, H, A]
backend: PipelineBackend[P, FormT, H, A, U]
) -> CorePipelineResult[FormT]:
full_ctx = WorkflowContext.create(
services=conns.memory,
Expand Down
Loading
Loading