# Project export: Etch

This document was generated by HackStack to give an AI agent context about a hackathon project. Sections are labeled with their provenance; content marked as truncated was cut to keep this document small.

## Project metadata

- Hackathon: UC Berkeley AI Hackathon 2026
- Tagline: Etch turns a plain-English chip requirement into verified RTL—proposing candidates, then proving trust through real simulation, formal, and synthesis gates. AI proposes; only evidence wins.
- Devpost: https://devpost.com/software/etch-3kg4d9
- GitHub: https://github.com/ezzy1630/Etch
- Video: https://www.youtube.com/embed/qyV6stLBVX4?enablejsapi=1&hl=en_US&rel=0&start=&version=3&wmode=transparent
- Team: 5 GitHub contributor(s) — Ezzy Rappeport (24 commits), justin06lee (16 commits), Cofee Coder (13 commits), Claude Opus 4.8 (1M context) (5 commits), Cursor (1 commits)

## Devpost submission (written by the team)

### Inspiration

AI-generated code is everywhere, but hardware design has a uniquely unforgiving constraint: if a software script fails, you patch it; if a chip fails, you've wasted millions of dollars. We noticed that while LLMs can generate plausible-looking SystemVerilog that compiles, it often violates subtle safety properties. We were inspired by the gap between generation and trust. We didn't want to build just another AI wrapper that spits out code; we wanted to build a system where the AI's work is relentlessly interrogated and formally proven before it ever sees silicon.

### What it does

Etch is a verification-first hardware design cockpit. You give it a natural-language hardware requirement (like a synchronous FIFO), and Etch doesn't just give you one answer—it generates multiple candidate designs. Crucially, it then acts as a rigorous judge. It runs these candidates through a gauntlet of actual, industry-standard EDA (Electronic Design Automation) tools for simulation, formal verification, and synthesis. If a candidate has a bug (like an underflow error), Etch disqualifies it and shows you exactly why. It then ranks the surviving, proven designs by physical metrics like area size, and packages the entire run into an inspectable "proof dossier." It turns an ambiguous AI output into a falsifiable, trustworthy hardware artifact.

### How we built it

We designed Etch from the ground up to prioritize evidence over claims. We built a polished, Apple-like desktop workbench (using React) that makes the complex chip design loop feel legible. Instead of focusing purely on the LLM prompt engineering, we focused on the evaluation pipeline. We integrated real open-source verification tools (like SymbiYosys and Icarus) and created strict rules: correctness is a hard eligibility gate. Area or timing metrics cannot rescue a candidate that fails formal verification. We also intentionally separated the AI generation from the "oracle" that tests it, ensuring the system grades the AI's homework honestly.

### Challenges we ran into

Building trust in an automated hardware workflow is incredibly difficult. Hardware engineers are naturally (and rightfully) skeptical of AI. Our biggest product challenge was designing an interface that didn't hide failures or overclaim success. We had to figure out how to clearly communicate complex states—like when a tool is missing, when a design is formally falsified, or when evidence is just a proxy—without overwhelming the user with a generic, unreadable dashboard. We had to resist the urge to use "fake green success states" and ensure every UI element pointed directly to the underlying proof.

### Accomplishments we're proud of

We're incredibly proud that Etch actually catches AI mistakes. In our demo, we purposefully introduce a candidate with a subtle underflow defect, and the system successfully catches it, formally falsifies it, and provides a counterexample—exactly what a human verification engineer would demand. We are also proud of the cockpit's design. We achieved our goal of making the interface feel premium, exacting, and calm. We proved that you can take the incredibly dense, noisy world of hardware verification and make it accessible to a technical founder while remaining rigorous enough for an EDA-fluent engineer.

### What we learned

We learned that in the era of AI, generation is cheap, but evaluation is invaluable. The true durable product isn't the AI model writing the Verilog; it's the evidence-producing pipeline and the trust rules wrapped around it. We also learned how critical "evidence-first design" is—users only trust the automation if they can instantly click through to see the exact logs, gates, and constraints that produced the result.

### What's next

Right now, Etch is a polished vertical slice. Next, we want to expand it to handle a wider array of complex hardware components. We also plan to integrate the final stages of physical signoff (like OpenROAD for place-and-route and Magic for DRC/LVS) so that Etch can take a natural language prompt all the way to a routed, signoff-ready GDS file. Ultimately, we see Etch becoming the default desktop workbench where the next generation of silicon is designed, proven, and trusted. For the Token Company track, we extended this same evidence-first philosophy to agent context itself. Etch's hardware-agent traces — specs, RTL, testbenches, formal properties, failed checks, counterexamples, logs, and synthesis reports — are exactly the kind of evidence-heavy history where sloppy compaction is dangerous: dropping the wrong invariant or failure leaves a future agent continuing from a false view of the design. We used these traces as the substrate for exploring hardware-aware compaction, comparing behavior against systems like Caveman, OpenCode, and Codex-style workflows, with DiffusionGemma as our model direction since its bidirectional attention is well suited to judging which facts and relationships across a long trace are worth preserving. The goal is a learned compressor that treats compaction not as a token-saving trick but as a correctness problem — one where the compacted state still preserves the proof-relevant facts an agent needs to continue correctly.

## README (from the GitHub repository)

<p align="center">
  <img src="assets/etch-logo.svg" alt="Etch logo" width="180">
</p>

<h1 align="center">Etch</h1>

<p align="center">
  <strong>Verification-first hardware design from intent to evidence.</strong>
</p>

<p align="center">
  <a href="https://github.com/ezzy1630/Etch/actions/workflows/ci.yml"><img alt="CI" src="https://img.shields.io/github/actions/workflow/status/ezzy1630/Etch/ci.yml?branch=main&label=CI"></a>
  <img alt="Python 3.12+" src="https://img.shields.io/badge/Python-3.12%2B-3776AB">
  <img alt="Node 20.19+" src="https://img.shields.io/badge/Node-20.19%2B-339933">
  <img alt="Status" src="https://img.shields.io/badge/status-local%20vertical%20slice-111827">
</p>

Etch is a local hardware-design cockpit that turns a natural-language
requirement into a typed design spec, candidate RTL, independent verification
artifacts, EDA gate results, correctness-first ranking, physical/readiness
records, and a proof dossier.

The project is built around one principle: generating RTL is not enough. Etch
tracks why a candidate should be trusted, what evidence exists, what failed,
which tools were missing, and which claims are still out of bounds.

<p align="center">
  <img src="assets/etch-readme-architecture.svg" alt="Etch architecture overview" width="860">
</p>

## Current Shape

Etch's polished vertical slice is a synchronous FIFO design loop, backed by a
FastAPI service, a React/Vite workbench, an Electron desktop shell, local run
workspaces, deterministic demo artifacts, optional LLM proposal paths, and
tool adapters for open EDA flows.

Recent work added the autonomy and factory-planning spine around that loop:

| Surface | Current behavior |
|---|---|
| Workbench cockpit | Overview, Runs, Active Run, Chip, Candidates, Frontier, Artifacts, Trust, and Diagnostics views with status-aware navigation, a focus-oriented inspector, narrative/raw event console modes, recommended command palette actions, desktop-native copy commands, run controls, and steering actions. |
| Correctness gates | Simulation, bounded formal, synthesis, equivalence/profile records, scoring, finalist checkpoints, and proof dossiers. |
| Physical path | Macro strategy, proxy floorplan/macro placement, PlaceRoute/Routing records, reliability floors, DRC/LVS/signoff records, and explicit missing-tool states. |
| Benchmark ladder | FIFO through arbiter, AXI-lite, DMA, cache, RV32I, accelerator tile, and SoC integration milestones. |
| CPU ladder v2 | Planning records and local execution plans for CoreMark/Dhrystone, ISA compliance, interrupts/exceptions, cache/memory stress, branch-heavy workloads, Linux boot, and small application workloads. |
| Tournament engine | Deterministic correctness-first benchmark tournament planning with blocked-round handling, next actions, durable memory lessons, and review finding gates. |
| SoC bridge | Generator execution bridge v2 for configured Chipyard/Rocket-style roots, generated RTL import into Etch candidates, CPU validation farm records, OpenROAD blocker attempts, and FireSim readiness hooks. |
| Industrial program | CPU-program readiness, differential reference-trace verification plans, comparative open-core harness records, microarchitecture experiment-loop planners, validation-farm scheduler policy, physical-aware search scoring, Hammer-style flow abstraction, platform bring-up checks, closure recipe checks, PDK truth profiles, and explicit external-evidence requirements. |
| Scalable factory V1 | Persisted context bundles, versioned domain-pack binding, durable local job queue visibility, one-generation search expansion, evidence-first ranking snapshots, and steering provenance across API and cockpit surfaces. |
| Desktop packaging | A macOS DMG path that bundles the cockpit and frozen Python backend; Windows helper scripts are present for setup/dev/build flows. |

Etch does not claim production foundry signoff. Missing binaries, unpinned PDKs,
proxy-only analyses, unavailable rule decks, and incomplete verification
profiles remain visible as missing or blocked evidence.

## Quickstart

Install locked Python, web, and desktop dependencies:

```bash
make install
```

Start the API and web cockpit in separate terminals:

```bash
make backend-dev
make frontend-dev
```

Open the URL printed by Vite. In the **Runs** view, paste this prompt and start
a run:

```text
Design a synchronous FIFO with 8-bit data, depth 16, ready/valid-style ports, overflow/underflow protection, and a preference for small area.
```

CLI shortcuts:

```bash
make demo-live      # fresh deterministic FIFO pipeline with local tool discovery
make demo-backup    # load the committed, integrity-checked saved run
make desktop-dev    # Electron shell hosting the cockpit
make dmg            # macOS packaged app with bundled backend
```

For a line-by-line operator guide, see [RUN.md](RUN.md). For a two-minute judge
walkthrough, see [DEMO_SCRIPT.md](DEMO_SCRIPT.md).

## What The Demo Proves

The FIFO demo is intentionally small, because the point is evidence quality
rather than prompt size.

1. A natural-language requirement becomes a validated `DesignSpec`.
2. The deterministic demo creates three candidate implementations.
3. Candidate B contains an intentional underflow defect.
4. Independent oracle artifacts define simulation and formal gates.
5. Local tools run when installed; missing tools become `tool_missing`.
6. Failed, missing, or inconclusive evidence cannot become a proven winner.
7. The cockpit shows candidates, stage history, events, artifacts, physical
   status, trust posture, and proof limits.
8. Markdown and JSON proof dossiers preserve the final evidence story.

The canonical saved run is:

```text
run_01KV7E5MAB8GYA321BJMQ1PTTS
```

That saved run was produced with real open-source tools: Yosys 0.66,
Verilator, Icarus/VVP, SymbiYosys, `yosys-smtbmc`, Z3, and sky130 data. Candidate
A (`candidate_a_pointer_fifo`, about 5485 square microns) is the proven
correctness winner. Candidate C is proven but larger. Candidate B is falsified
by formal property `no_underflow` and diverges in simulation at cycle 1.

OpenROAD, Magic, KLayout, and Netgen were not installed for that saved run, so
place-and-route, DRC, and LVS are recorded as `tool_missing` or skipped. Physical
signoff is pending; the correctness claim stands on its own.

Saved dossier:
[examples/saved_runs/fifo_backup/run_01KV7E5MAB8GYA321BJMQ1PTTS/results/proof_dossier.md](examples/saved_runs/fifo_backup/run_01KV7E5MAB8GYA321BJMQ1PTTS/results/proof_dossier.md)

## Architecture

```mermaid
flowchart LR
    Prompt["Prompt"] --> Intake["Agent intake"]
    Intake --> Spec["Typed DesignSpec"]
    Spec --> Candidates["RTL candidates"]
    Spec --> Oracle["Independent oracle"]
    Candidates --> Gates["Simulation, formal, synthesis"]
    Oracle --> Gates
    Gates --> Score["Correctness-first scoring"]
    Score --> Physical["Frontier, macro, physical, signoff records"]
    Physical --> Dossier["Proof dossier"]
    Dossier --> Workspace[("Run workspace")]
    Workspace --> API["FastAPI"]
    API --> UI["React/Electron cockpit"]
```

The file-backed run workspace is the system of record:

```text
runs/{run_id}/
  run.json
  events.jsonl
  artifacts.json
  prompt_metadata.json
  design_spec.json
  candidates/
  oracle/
  simulation/
  formal/
  synthesis/
  physical/
  evolution/
  context/
  results/
  logs/
```

More detail lives in [ARCHITECTURE.md](ARCHITECTURE.md), including component
boundaries, data flow, trust boundaries, and the "more than a model wrapper"
argument.

## Trust Model

AI can propose artifacts; it cannot award trust.

When configured, Gemini, OpenAI, or Anthropic can propose typed specs, candidate
RTL, verification artifacts, and one repair candidate. Etch then applies schema
validation, interface checks, tool execution, persisted stdout/stderr, gate
records, deterministic scoring, and dossier generation.

The deterministic three-candidate FIFO demo is not described as live model

[README truncated for size]

## Detected evidence (automated analysis)

Indexed codebase: 593 recognized source files, 5885 KB.
- CSS (language) — detected in the code
- FastAPI (technology) — detected in the code
- HTML (language) — detected in the code
- JavaScript (language) — detected in the code
- Python (language) — detected in the code
- React (technology) — detected in the code
- Tailwind CSS (technology) — detected in the code
- TypeScript (language) — detected in the code
- Anthropic (technology) — claimed on Devpost, not found in the code
- Docker (technology) — claimed on Devpost, not found in the code
- Google Gemini (technology) — claimed on Devpost, not found in the code
- OpenAI (technology) — claimed on Devpost, not found in the code
- AI coding agent: Claude Code — evidence: commit authorship or trailers
- AI coding agent: Cursor — evidence: commit authorship or trailers

## Codebase structure (from repository index)

### Files (120 of 767)

```
.env.example
.github/workflows/ci.yml
.gitignore
apps/api/src/etch_api/__init__.py
apps/api/src/etch_api/app.py
apps/api/src/etch_api/auth.py
apps/api/src/etch_api/chat_router.py
apps/api/src/etch_api/chat_ws.py
apps/api/src/etch_api/chat/__init__.py
apps/api/src/etch_api/chat/agent.py
apps/api/src/etch_api/chat/anthropic_stream.py
apps/api/src/etch_api/chat/codex_app_server.py
apps/api/src/etch_api/chat/config.py
apps/api/src/etch_api/chat/mcp_server.py
apps/api/src/etch_api/chat/store.py
apps/api/src/etch_api/chat/tools.py
apps/api/src/etch_api/config.py
apps/api/src/etch_api/dependencies.py
apps/api/src/etch_api/env_file.py
apps/api/src/etch_api/events_ws.py
apps/api/src/etch_api/examples_router.py
apps/api/src/etch_api/library_router.py
apps/api/src/etch_api/library/__init__.py
apps/api/src/etch_api/library/store.py
apps/api/src/etch_api/meta_router.py
apps/api/src/etch_api/runs_router.py
apps/api/src/etch_api/runs/__init__.py
apps/api/src/etch_api/runs/artifact_content.py
apps/api/src/etch_api/runs/artifact_views.py
apps/api/src/etch_api/runs/commands.py
apps/api/src/etch_api/runs/read_queries.py
apps/api/src/etch_api/schemas.py
apps/api/tests/conftest.py
apps/api/tests/test_anthropic_stream.py
apps/api/tests/test_app_cors.py
apps/api/tests/test_artifacts.py
apps/api/tests/test_auth.py
apps/api/tests/test_chat_agent.py
apps/api/tests/test_chat_config.py
apps/api/tests/test_chat_mcp_server.py
apps/api/tests/test_chat_router.py
apps/api/tests/test_chat_store.py
apps/api/tests/test_chat_tools.py
apps/api/tests/test_chat_ws.py
apps/api/tests/test_codex_app_server.py
apps/api/tests/test_context_endpoints.py
apps/api/tests/test_demo_fifo.py
apps/api/tests/test_domain_packs.py
apps/api/tests/test_env_file.py
apps/api/tests/test_events_ws.py
apps/api/tests/test_evolution_decision.py
apps/api/tests/test_examples.py
apps/api/tests/test_health.py
apps/api/tests/test_library.py
apps/api/tests/test_runs.py
apps/api/tests/test_saved_demo.py
apps/api/tests/test_steering.py
apps/desktop/backend/etch_backend_main.py
apps/desktop/package.json
apps/desktop/src/main/backend.ts
apps/desktop/src/main/index.ts
apps/desktop/src/main/menu.ts
apps/desktop/src/main/window.ts
apps/desktop/src/preload/preload.ts
apps/desktop/src/shared/bridge.ts
apps/desktop/src/shared/ipc-channels.ts
apps/desktop/src/shared/menu-actions.ts
apps/desktop/test/security.test.mjs
apps/desktop/tsconfig.json
apps/desktop/web-dist/assets/ChipSceneCanvas-DMT8iJdp.js
apps/desktop/web-dist/assets/index-CSP9c9X9.css
apps/desktop/web-dist/assets/index-D92MYG1Q.js
apps/desktop/web-dist/index.html
apps/web/index.html
apps/web/package.json
apps/web/src/App.test.ts
apps/web/src/App.tsx
apps/web/src/client/actionAvailability.ts
apps/web/src/client/chat.test.ts
apps/web/src/client/chat.ts
apps/web/src/client/client.test.ts
apps/web/src/client/commands.ts
apps/web/src/client/config.ts
apps/web/src/client/desktop-bridge.ts
apps/web/src/client/EtchClient.ts
apps/web/src/client/events.test.ts
apps/web/src/client/events.ts
apps/web/src/client/http.ts
apps/web/src/client/index.ts
apps/web/src/client/library.ts
apps/web/src/client/reads.ts
apps/web/src/client/types.ts
apps/web/src/components/chat/ChatComposer.tsx
apps/web/src/components/chat/ChatHome.test.tsx
apps/web/src/components/chat/ChatHome.tsx
apps/web/src/components/chat/ChatMessage.test.tsx
apps/web/src/components/chat/ChatMessage.tsx
apps/web/src/components/chat/ChatView.test.tsx
apps/web/src/components/chat/ChatView.tsx
apps/web/src/components/chat/RunNarrative.test.tsx
apps/web/src/components/chat/RunNarrative.tsx
apps/web/src/components/chat/ThinkingBlock.tsx
apps/web/src/components/chat/ToolCallCard.tsx
apps/web/src/components/context/ContextMenu.tsx
apps/web/src/components/evidence/CounterexamplePanel.tsx
apps/web/src/components/evidence/EvidenceViewer.tsx
apps/web/src/components/evidence/WaveformViewer.tsx
apps/web/src/components/evolution/EvolutionViewer.tsx
apps/web/src/components/evolution/RunStage.test.ts
apps/web/src/components/evolution/RunStage.tsx
apps/web/src/components/gates/CandidateGateInspection.tsx
apps/web/src/components/gates/GateCard.tsx
apps/web/src/components/icons.tsx
apps/web/src/components/intake/ContextBundlePanel.tsx
apps/web/src/components/intake/DomainPackPicker.tsx
apps/web/src/components/library/LibrarySidebar.tsx
apps/web/src/components/macro-placement/data.ts
apps/web/src/components/macro-placement/EvoCandidateViewer.tsx
apps/web/src/components/macro-placement/MacroPlacementStandaloneHarness.test.ts
apps/web/src/components/macro-placement/MacroPlacementStandaloneHarness.tsx
[647 more files omitted for size]
```

### Dependencies

- apps/desktop/package.json: @types/node@^22.13.10, electron@^42.4.0, electron-builder@^26.15.3, esbuild@^0.28.1, typescript@^5.8.0
- apps/web/package.json: @tailwindcss/vite@^4.3.1, @testing-library/react@^16.3.2, @types/react@^19.0.0, @types/react-dom@^19.0.0, @types/three@^0.172.0, @vitejs/plugin-react@^5.0.0, jsdom@^29.1.1, motion@^12.40.0, react@^19.0.0, react-dom@^19.0.0, tailwindcss@^4.3.1, three@^0.172.0, typescript@^5.8.0, vite@^8.0.16, vitest@^4.1.8
- pyproject.toml: cryptography@>=42.0, fastapi@>=0.115, opentelemetry-exporter-otlp-proto-http@>=1.20, opentelemetry-sdk@>=1.20, pydantic@>=2.10, pyslang@>=7.0, pyyaml@>=6.0, sentry-sdk@>=2.0, uvicorn[standard]@>=0.32

### Recent commits (newest first)

- changes
- Merge remote-tracking branch 'refs/remotes/origin/main'
- changes
- Fix Codex app-server transport
- Merge remote-tracking branch 'refs/remotes/origin/main'
- Persist Codex chat threads
- changes
- api: add Etch MCP tool bridge for Codex
- feat(web): create chats as chips inside library folders (#8)
- merge: integrate macro placement backend
- merge: integrate UI redesign
- lots of front end
- Pin Volare sky130 PDK revision
- Merge pull request #7 from ezzy1630/feat/ui-redesign
- Merge remote-tracking branch 'origin/main' into feat/ui-redesign
- feat(ui): redesign styles + eda/core refinements; rebuild desktop web-dist
- Productionization + real sky130 silicon flow + agentic chat UI (#6)
- fix: codebase-wide audit sweep — bugs, security, dead code (#5)
- idk
- feat: add factory context run helpers

## Key source files (fetched from GitHub, selected and truncated for size)

### PRODUCT.md

```markdown
# Product

## Register

product

## Users

Etch serves a hybrid primary user: a hardware or EDA-fluent engineer who needs
real evidence, and a technical founder, judge, or evaluator who needs the chip
design loop explained clearly enough to trust it. They use Etch in a desktop
workbench context, moving between a hardware prompt, a live or cached run,
candidate evidence, proof limits, physical status, and artifacts.

## Product Purpose

Etch turns a natural-language hardware requirement into candidate RTL designs,
independent verification evidence, correctness-first scoring, physical and
signoff status, and a proof dossier. The cockpit exists to make that loop feel
inspectable, falsifiable, and operational: users should always understand what
ran, what failed, what is missing, which candidate is selected, and what action
is available next.

## Brand Personality

Polished, exacting, calm. Etch should feel close to Cursor and Codex as a
desktop workbench, with Apple-like clarity in the way controls, menus, states,
and defaults behave. It should be beautiful without becoming decorative, dense
without becoming cryptic, and cinematic only where the chip/proof story benefits.

## Anti-references

Etch should not look like a generic dark dashboard, a VS Code skin with
inconsistent controls, a marketing demo wrapped around a table, or a chip-themed
visual toy that overclaims proof. Avoid fake green success states, gratuitous
motion, decorative gradients, unclear icon-only controls, hidden disabled
reasons, unexplained empty states, and any interface that makes missing tools or
proxy physical data look complete.

## Design Principles

1. Evidence first: every status should point toward the artifact, gate, limit,
   or missing input that explains it.
2. Current context is always visible: run, stage, selected candidate, proof
   posture, and next action should be legible without hunting.
3. Power stays quiet: expert tools, inspectors, consoles, and commands should be
   available without overwhelming the main path.
4. Controls are promises: every button, menu, disabled state, and shortcut must
   clearly signal what it does and respond consistently.
5. Premium moments serve comprehension: animation and visual richness belong in
   chip construction, evidence reveal, and state transitions, not decoration.

## Accessibility & Inclusion

Target WCAG AA contrast for text and controls. Preserve keyboard access for
navigation, command palette, run controls, candidate selection, chip controls,
and artifact actions. Respect reduced-motion preferences. Use text, shape, and
labels in addition to color for pass, fail, warning, proxy, cached, skipped, and
missing-tool states. Long IDs, paths, logs, and dossier content must wrap,
truncate, or scroll inside stable containers.

```

### ARCHITECTURE_REVIEW.md

```markdown
# Etch Architecture Review

Date: 2026-06-16

## Verdict

No, the old architecture should not be kept. The broad buckets
`etch_core`, `etch_agent`, and `etch_eda` are gone. The current backend uses
concrete packages that match actual responsibilities instead of preserving a
central model facade or generic wrapper chain.

## Current Backend Map

```mermaid
flowchart LR
    API["etch_api\nHTTP/events transport"]
    RunLifecycle["run_lifecycle\nrun create/read commands"]
    Pipeline["pipeline\nstage execution"]
    Agents["agents\nprovider, intake, import, demo"]
    Gates["gates\nequivalence, simulation, formal"]
    Physical["physical\nsynthesis, floorplan, pnr, signoff"]
    Toolkit["toolkit\ntool subprocess harness"]
    Workspace["workspace\nrun folders, artifacts, events"]
    Contracts["contracts\ntyped records and ids"]
    Selection["selection\nscoring, frontier, dossiers"]
    Memory["memory\nfuture durable project memory"]

    API --> RunLifecycle
    API --> Pipeline
    RunLifecycle --> Workspace
    RunLifecycle --> Pipeline
    Pipeline --> Agents
    Pipeline --> Gates
    Pipeline --> Physical
    Pipeline --> Selection
    Agents --> Contracts
    Gates --> Contracts
    Physical --> Contracts
    Selection --> Contracts
    Workspace --> Contracts
    Gates --> Toolkit
    Physical --> Toolkit
```

## What Is Fixed

- The old `etch_core`, `etch_agent`, and `etch_eda` package buckets were deleted.
- `etch_core.models` is no longer a facade; shared records live in `contracts`.
- `contracts/contracts` was flattened into `contracts.oracle`,
  `contracts.evidence`, `contracts.closure`, and `contracts.memory`.
- The run lifecycle package was renamed from `runs` to `run_lifecycle` because
  the repo-level `runs/` data directory made `runs` an unsafe Python package
  name under editable installs.
- `pipeline.jobs` now owns job lifecycle state and readiness behavior instead
  of re-exporting those types from `pipeline.stage_graph`.
- `RunService.create_run` now creates the run folder/event and delegates
  materialization policy to `pipeline.intake.materialize_created_run`.
- `/pipeline/stages` is the current stage-graph API. `/orchestration/stages`
  remains only as a deprecated compatibility alias.
- Windows setup/check scripts now include desktop install, test, and build work.

## Remaining Architecture Work

1. Historical plans in `docs/superpowers/plans/` are implementation provenance,
   not current executable guidance unless rewritten to the concrete packages.

## Current Guardrails

- `packages/core/tests/test_backend_package_architecture.py` checks concrete
  package importability, expected source roots, removed legacy package buckets,
  no production imports from old model buckets, and no duplicate
  `contracts/contracts` package.
- `packages/core/tests/test_windows_scripts.py` checks that Windows setup and
  verification include both web and desktop packages.

```

### pyproject.toml

```
[build-system]
requires = ["setuptools>=80", "wheel"]
build-backend = "setuptools.build_meta"

[project]
name = "etch"
version = "0.1.0"
description = "Verification-first hardware design cockpit."
readme = "README.md"
requires-python = ">=3.12"
dependencies = [
  "fastapi>=0.115",
  "pyyaml>=6.0",
  "uvicorn[standard]>=0.32",
  "pydantic>=2.10",
]

[project.optional-dependencies]
observability = [
  "sentry-sdk>=2.0",
  # OpenTelemetry export to Arize Phoenix (or any OTLP collector). Optional:
  # the tracing layer no-ops when these and an endpoint are absent.
  "opentelemetry-sdk>=1.20",
  "opentelemetry-exporter-otlp-proto-http>=1.20",
]
# Encrypted-at-rest secret store. Optional: SecretStore falls back to a
# stdlib authenticated construction when 'cryptography' is not installed.
secrets = [
  "cryptography>=42.0",
]
# In-process SystemVerilog parser for high-fidelity RTL import (Spec 20 §5.2).
# Optional: the importer falls back to a reduced-fidelity multi-file regex path
# when pyslang is not installed, so the app builds and tests pass without it.
rtl-import = [
  "pyslang>=7.0",
]

[tool.setuptools.packages.find]
where = [
  "apps/api/src",
  "packages/agent/src",
  "packages/core/src",
  "packages/eda/src",
]
include = [
  "agents*",
  "contracts*",
  "eda_capabilities*",
  "gates*",
  "generators*",
  "memory*",
  "physical*",
  "pipeline*",
  "run_lifecycle*",
  "selection*",
  "toolkit*",
  "workspace*",
  "etch_api*",
]

[tool.pytest.ini_options]
testpaths = [
  "apps/api/tests",
  "packages/core/tests",
  "packages/eda/tests",
  "packages/agent/tests",
]
addopts = "-q"
markers = [
  "integration: tests that require live EDA tools or solver binaries",
]

[dependency-groups]
dev = [
  "pytest>=8.3",
  # httpx2 (not httpx) is intentional: the locked starlette release's TestClient
  # imports `httpx2 as httpx` first and only falls back to plain httpx with a
  # deprecation warning. Do not "fix" this back to httpx.
  "httpx2>=2.3",
  "pyinstaller>=6.21.0",
]

[tool.uv]
default-groups = ["dev"]

```

### Dockerfile

```
FROM ubuntu:22.04

ENV DEBIAN_FRONTEND=noninteractive
SHELL ["/bin/bash", "-o", "pipefail", "-c"]

ENV OSS_CAD_SUITE=/opt/oss-cad-suite
ENV PATH="${OSS_CAD_SUITE}/bin:/usr/local/bin:${PATH}"
ENV PDK_ROOT=/pdk

RUN apt-get update && apt-get install -y --no-install-recommends \
    build-essential \
    ca-certificates \
    cmake \
    freeglut3-dev \
    git \
    iverilog \
    klayout \
    libcairo2-dev \
    libglu1-mesa-dev \
    libreadline-dev \
    libx11-dev \
    libxpm-dev \
    m4 \
    python3-pip \
    tcl-dev \
    tk-dev \
    verilator \
    wget \
    && rm -rf /var/lib/apt/lists/*

RUN python3 - <<'PY'
import json
import os
import tarfile
import tempfile
import urllib.request

api_url = "https://api.github.com/repos/YosysHQ/oss-cad-suite-build/releases/latest"
request = urllib.request.Request(api_url, headers={"User-Agent": "etch-toolchain-build"})
with urllib.request.urlopen(request) as response:
    release = json.load(response)

asset = next(
    (
        asset
        for asset in release["assets"]
        if asset["name"].startswith("oss-cad-suite-linux-x64-")
        and asset["name"].endswith(".tgz")
    ),
    None,
)
if asset is None:
    raise SystemExit("No linux-x64 OSS CAD Suite tarball found in the latest release")

os.makedirs("/opt", exist_ok=True)
with tempfile.NamedTemporaryFile(suffix=".tgz") as archive:
    print(f"Downloading {asset['name']}")
    urllib.request.urlretrieve(asset["browser_download_url"], archive.name)
    with tarfile.open(archive.name, "r:gz") as tar:
        tar.extractall("/opt")
PY

RUN python3 - <<'PY'
import json
import os
import tempfile
import urllib.request

api_url = "https://api.github.com/repos/Precision-Innovations/OpenROAD/releases?per_page=30"
request = urllib.request.Request(api_url, headers={"User-Agent": "etch-toolchain-build"})
with urllib.request.urlopen(request) as response:
    releases = json.load(response)

matches = []
for release in releases:
    for asset in release.get("assets", []):
        name = asset["name"]
        if name.endswith(".deb") and (
            "ubuntu-22.04" in name or "ubuntu22.04" in name
        ):
            matches.append((release["tag_name"], asset))

if not matches:
    raise SystemExit("No Ubuntu 22.04 OpenROAD .deb found in recent Precision Innovations releases")

tag, asset = matches[0]
download_path = "/tmp/openroad.deb"
print(f"Downloading OpenROAD {tag}: {asset['name']}")
urllib.request.urlretrieve(asset["browser_download_url"], download_path)
PY

RUN apt-get update \
    && apt-get install -y --no-install-recommends /tmp/openroad.deb \
    && rm -f /tmp/openroad.deb \
    && rm -rf /var/lib/apt/lists/*

RUN git clone --depth 1 https://github.com/RTimothyEdwards/magic.git /tmp/magic \
    && cd /tmp/magic \
    && ./configure \
    && make -j"$(nproc)" \
    && make install \
    && rm -rf /tmp/magic

RUN git clone --depth 1 https://github.com/RTimothyEdwards/netgen.git /tmp/netgen \
    && cd /tmp/netgen \
    && ./configure \
    && make -j"$(nproc)" \
    && make install \
    && rm -rf /tmp/netgen

RUN pip3 install --no-cache-dir --upgrade pip \
    && pip3 install --no-cache-dir cocotb librelane volare

WORKDIR /workspace

CMD ["/bin/bash"]

```

### apps/web/package.json

```
{
  "name": "@etch/web",
  "version": "0.1.0",
  "private": true,
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "tsc -b && vite build",
    "preview": "vite preview",
    "test": "vitest run"
  },
  "dependencies": {
    "motion": "^12.40.0",
    "react": "^19.0.0",
    "react-dom": "^19.0.0",
    "three": "^0.172.0"
  },
  "devDependencies": {
    "@tailwindcss/vite": "^4.3.1",
    "@testing-library/react": "^16.3.2",
    "@types/react": "^19.0.0",
    "@types/react-dom": "^19.0.0",
    "@types/three": "^0.172.0",
    "@vitejs/plugin-react": "^5.0.0",
    "jsdom": "^29.1.1",
    "tailwindcss": "^4.3.1",
    "typescript": "^5.8.0",
    "vite": "^8.0.16",
    "vitest": "^4.1.8"
  }
}

```

### apps/desktop/package.json

```
{
  "name": "@etch/desktop",
  "version": "0.1.0",
  "private": true,
  "description": "Etch desktop shell (Electron main + preload)",
  "main": "dist/main/index.js",
  "author": "Etch",
  "scripts": {
    "build": "tsc -p tsconfig.json && npm run build:preload",
    "build:preload": "esbuild src/preload/preload.ts --bundle --platform=node --format=cjs --target=es2022 --external:electron --outfile=dist/preload/preload.js",
    "dev": "npm run build && electron .",
    "start": "npm run build && electron .",
    "dist": "npm run build && electron-builder --mac dmg",
    "test": "node --test test/security.test.mjs"
  },
  "devDependencies": {
    "@types/node": "^22.13.10",
    "electron": "^42.4.0",
    "electron-builder": "^26.15.3",
    "esbuild": "^0.28.1",
    "typescript": "^5.8.0"
  },
  "build": {
    "appId": "hack.winners.etch",
    "productName": "Etch",
    "directories": {
      "output": "release",
      "buildResources": "build"
    },
    "files": [
      "dist/**/*",
      "web-dist/**/*",
      "package.json"
    ],
    "extraResources": [
      {
        "from": "../../build/desktop-backend/etch-backend",
        "to": "backend"
      }
    ],
    "mac": {
      "category": "public.app-category.developer-tools",
      "icon": "build/icon.icns",
      "identity": null,
      "target": [
        {
          "target": "dmg"
        }
      ]
    },
    "dmg": {
      "title": "Etch ${version}",
      "background": "build/dmg-background.png",
      "iconSize": 112,
      "window": {
        "width": 512,
        "height": 512
      },
      "contents": [
        {
          "x": 150,
          "y": 275,
          "type": "file"
        },
        {
          "x": 358,
          "y": 275,
          "type": "link",
          "path": "/Applications"
        }
      ]
    }
  }
}

```

### apps/web/src/App.tsx

```typescript
import { ChatHome } from "./components/chat/ChatHome";
import { ErrorBoundary } from "./components/ui/ErrorBoundary";

export {
  formatStatusLabel,
  getEventTone,
  parseVerificationLimits,
  describeAutonomyTournamentCapability,
  summarizePhysicalStatus,
} from "./lib/presentation";

export function App() {
  // Top-level backstop: a render error anywhere can never blank the whole app.
  return (
    <ErrorBoundary label="Etch hit an unexpected error">
      <ChatHome />
    </ErrorBoundary>
  );
}

```

### apps/web/src/main.tsx

```typescript
import React from "react";
import ReactDOM from "react-dom/client";
import { MotionConfig } from "motion/react";

import { App } from "./App";
// tailwind.css imports styles.css into the `legacy` layer so Tailwind utilities
// win over the workbench's global reset; do not import styles.css separately.
import "./tailwind.css";

// One snappy, subtle spring for the whole app — fast settle, minimal overshoot —
// so layout glides and micro-interactions feel consistent. `reducedMotion="user"`
// honors the OS "reduce motion" setting (animations collapse to instant).
export const SNAPPY = { type: "spring", stiffness: 460, damping: 40, mass: 0.8 } as const;

// Running inside the Electron desktop shell: enable the frameless title-bar
// styling (traffic lights overlay the cockpit) via the `.etch-desktop` class.
if (typeof window !== "undefined" && window.etchDesktop) {
  document.documentElement.classList.add("etch-desktop");
}

ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
  <React.StrictMode>
    <MotionConfig reducedMotion="user" transition={SNAPPY}>
      <App />
    </MotionConfig>
  </React.StrictMode>,
);

```

### apps/web/src/client/index.ts

```typescript
export * from "./types";
export * from "./config";
export * from "./http";
export * from "./reads";
export * from "./commands";
export * from "./events";
export * from "./actionAvailability";
export { EtchClient, etchClient, type ConnectionListener } from "./EtchClient";

```

### apps/api/src/etch_api/app.py

```python
import os

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

from etch_api import __version__
from etch_api.env_file import load_env_files
from etch_api.chat_router import router as chat_router
from etch_api.chat_ws import router as chat_ws_router
from etch_api.events_ws import router as events_ws_router
from etch_api.examples_router import router as examples_router
from etch_api.library_router import router as library_router
from etch_api.meta_router import router as meta_router
from etch_api.runs_router import router as runs_router

# Populate os.environ from .env.local / .env (repo root) before any config is
# read, so secrets like ANTHROPIC_API_KEY can live in a gitignored file instead
# of being exported each session. Real environment variables still take priority.
load_env_files()


app = FastAPI(
    title="Etch API",
    version=__version__,
    description="API for the Etch proof-carrying hardware cockpit.",
)

_LOCAL_DEV_ORIGINS = [
    "http://localhost:5173",
    "http://127.0.0.1:5173",
    "http://localhost:5174",
    "http://127.0.0.1:5174",
    "http://localhost:4173",
    "http://127.0.0.1:4173",
]
_ETCH_ENV = os.environ.get("ETCH_ENV", "development").strip().lower()
_ALLOW_HEADERS = ["*"] if _ETCH_ENV == "development" else ["Content-Type", "Authorization", "Accept"]

app.add_middleware(
    CORSMiddleware,
    allow_origins=_LOCAL_DEV_ORIGINS,
    allow_origin_regex=r"^(null|https?://(localhost|127\.0\.0\.1):\d+)$",
    allow_methods=["GET", "POST", "OPTIONS"],
    allow_headers=_ALLOW_HEADERS,
)

app.include_router(runs_router)
app.include_router(runs_router, prefix="/api/v1")
app.include_router(chat_router)
app.include_router(chat_router, prefix="/api/v1")
app.include_router(library_router)
app.include_router(library_router, prefix="/api/v1")
app.include_router(events_ws_router)
app.include_router(events_ws_router, prefix="/api/v1")
app.include_router(chat_ws_router)
app.include_router(chat_ws_router, prefix="/api/v1")
app.include_router(meta_router)
app.include_router(examples_router)

```

[571 more indexed source files omitted to keep this export small. The full file list is in the Codebase structure section above.]