Skip to content

feat(agent): add agent supported features - #261

Open
YihangQiu wants to merge 99 commits into
mainfrom
yhqiu/flow-agent-v2
Open

YihangQiu wants to merge 99 commits into
mainfrom
yhqiu/flow-agent-v2

Conversation

@YihangQiu

@YihangQiu YihangQiu commented Sep 5, 2026

Copy link
Copy Markdown
Collaborator

What Changed

Scope

Select the areas touched by this PR:

  • CLI - command behavior, Typer command surface, output formats, or workspace commands.
  • Flow/runtime - workspace lifecycle, EngineFlow, step execution, logs, metrics, or artifacts.
  • EDA integration - Yosys, ECC-Tools, DreamPlace, KLayout, PDKs, or native/runtime wrappers.
  • Build/package - Nix, PyInstaller, wheels, uv.lock, or release artifacts.
  • CI/release - GitHub Actions, version checks, changelog, or release automation.
  • Tests/docs only

Runtime And Packaging Impact

  • No runtime or packaging impact
  • CLI output or machine-readable contract changed
  • Workspace layout, flow state, or artifact paths changed
  • Native toolchain or wrapper behavior changed
  • ecc-tools or ecc-dreamplace dependency changed
  • PyInstaller, Nix, or release artifact changed

Notes:

Validation

List the commands you ran. Mark checks that are not applicable as N/A.

  • uv run pytest test/
  • uv run ruff check chipcompiler test
  • uv run ruff format --check chipcompiler test
  • PyInstaller smoke: ecc --help, ecc --version, ecc version --json
  • Nix smoke: nix run .#cli -- --help
  • Manual flow smoke:
  • Other:

Skipped checks and reason:

Checklist

  • I kept the change scoped to ECC.
  • I updated docs or user-facing CLI text where behavior changed.
  • I included lockfile or version metadata updates when dependencies changed.
  • I documented any submodule updates and why they are needed.
  • I did not include local caches, virtual environments, or generated build outputs.
  • I explained skipped validation and remaining risk.

Emin017 and others added 30 commits August 31, 2026 20:10
Lift the legalization owner check so Timing Opt can reuse DreamPlace
legalize-only, load ECC from explicit DEF/Verilog, and skip the
pre-sizer input DB.
Stage Sizer DEF/Verilog under data/to, rebuild ECC from those files,
run DreamPlace legalize-only, and publish only the post-legalize
layout. Drop the cached EngineDB after any sizer terminal state.
Honor read_def failure, close abandoned engines, and load explicit
sources once. Fill the workspace DreamPlace config path before inner
legalization if the map is empty.
Clear previous staging before launching Sizer, and delete published
Timing Opt files on every unsuccessful save, including exceptions.
Raise if staging or published artifacts cannot be deleted, and reset
Timing Opt subflow stages at the start of every Sizer attempt.
Register Timing Opt/sizer workspace configs so `ecc config` can inspect
the db and DreamPlace files the inner legalize path actually reads.
Split the oversized sizer runner tests into runner, cleanup, and
EngineFlow modules.
Restore create_db_engine(workspace, step). Timing Opt inner legalize
now replace()s a local step with staging DEF/Verilog and db=None
instead of adding loader kwargs.
Opening an old one-stage Sizer workspace rewrote subflow stages to
Unstart but left the outer step Success, so resume skipped Timing Opt
and routed the unlegalized DEF. Persistently unstart the owner and its
downstream suffix when that rewrite happens.
Insert sizer Timing Opt into the default rtl2gds/harden sequence
between legalization and routing so CTS cleanup still happens first
and Sizer sees a legal layout.
Download the latest successful linux-x64 Sizer build before pytest and
export PATH plus CHIPCOMPILER_ECC_SIZER_ROOT so default-flow Timing Opt
can run in CI.
Stop opening step.log.file with write truncation. Sizer now inherits
the EngineFlow stdio capture so GUI still shows the sizer error when
inner legalize later writes its own DreamPlace log.
Sizer now exposes build_step_metrics so EngineFlow can write
qor_metrics/summary after a successful Timing Opt. Reuse the
legalization DB summary and skip the Sizer binary check so QoR
refresh still works when Sizer is only needed at run time.
Candidate reruns and resumes now register their runtime operation under
the cloned candidate's own identity (<source>::candidate::<candidate_id>)
instead of the source workspace id, and split into two phases: the parent
snapshot (preflight + clone / load + verify) runs briefly under the
source mutation lock and refuses while the source workspace owns an
active operation, while the long EDA execution runs in the isolated
candidate workspace without holding the source lock. Sibling candidates
therefore execute concurrently, plain source operations keep their
exclusive active-operation slot, and the RPC error text keeps mapping to
the agent's busy-defer contract. Step stdio redirection takes the shared
redirect lock so concurrent candidate steps cannot interleave the fd
dup2/rebind; tool subprocesses still inherit correctly routed fds.

The agent-side adapter stops refusing a second concurrent start and
accepts the derived candidate operation identity while still rejecting
foreign workspaces and deferring on a busy source workspace.
# Conflicts:
#	.github/actions/build-pyinstaller-bundle/action.yml
#	test/packaging/test_cli_entrypoint.py

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.

🟡 Changes recommended

There are correctness/portability issues to address in the new agent receipt context logic and one newly added test file violates the repo’s “no __future__ imports” guideline.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR expands ECC’s optional “agent” runtime surface by adding a dedicated ecc-agent-rpc JSON-RPC stdio entrypoint (packaged via PyInstaller) plus supporting candidate execution behaviors (rerun/resume, evidence/receipts, and agent-only runtime helpers).

Changes:

  • Add ecc-agent-rpc entrypoint (PyPI script + PyInstaller hard-linked alias) and smoke tests to ensure it responds with agent capabilities.
  • Extend agent runtime APIs and execution flow for isolated candidate workspaces (resume support, config preservation, receipts/evidence, and floorplan mode persistence).
  • Add agent-focused runtime utilities (Sizer environment prep/preflight, parallel STA worker orchestration, parameter runtime observation/reporting) with broad test coverage.
File summaries
File Description
test/tools/ecc_dreamplace/test_module.py Extends DreamPlace config param coverage (random seed).
test/test_engine_flow.py Verifies initialize_config can be disabled when building step workspaces.
test/runtime/test_workspace_api.py Asserts default runtime flow construction uses rtl2gds flow.
test/runtime/test_stdio_server.py Adds regression coverage for stdio protocol isolation from background stdout.
test/packaging/test_run_ecc.py Tests packaged entrypoint routing and exit-code propagation.
test/packaging/test_cli_entrypoint.py Adjusts packaging assertions and verifies agent RPC reuses the same PyInstaller Analysis/exe.
test/engine/test_state_machine_regression.py Removes legacy agent regression from core engine tests.
test/cli/test_rpc_cli.py Ensures CLI help doesn’t expose an --agent flag.
pyproject.toml Adds ecc-agent-rpc script and includes agent in build backend module list.
packaging/run_ecc.py Routes packaged entrypoint to agent RPC vs CLI based on argv stem; propagates exit code.
ecc.spec Creates ecc-agent-rpc as a hardlink to the ecc PyInstaller executable.
chipcompiler/runtime/stdio_server.py Redirects process stdout to stderr while keeping protocol writes on a dup’d fd.
chipcompiler/runtime/operations.py Introduces RuntimeOperationFailed and preserves partial results in failure/cancel events.
chipcompiler/engine/flow.py Adds initialize_config parameter to create_step_workspaces and passes through to step creation.
agent/workspace_api.py Major expansion: candidate rerun lifecycle, cloning/locking, receipts, evidence, preflight, resume plumbing.
agent/tools.py Wraps tool execution with parameter observation, floorplan mode application, STA parallel routing, and loader isolation.
agent/test/test_tools.py Tests plot suppression, loader isolation, runtime report ownership, and STA routing behavior.
agent/test/test_sta_parallel.py Tests Linux parent-death signal handling, worker lifecycle, cancellation, and memory tracking.
agent/test/test_sta_benchmark.py Tests benchmark inventory filtering and STA metric coverage validation/comparison.
agent/test/test_runtime.py Tests agent runtime environment prep and structured operation failure/result retention.
agent/test/test_requests.py Extends request parsing/validation and adds RPC entrypoint capability checks.
agent/test/test_parameter_status.py Validates parameter-status thresholds for DREAMPlace observations.
agent/test/test_parameter_runtime_observer.py Tests parameter observation hooks and report construction semantics.
agent/test/test_parameter_receipt_artifacts.py Tests parameter application receipt binding and artifact integrity.
agent/test/test_floorplan_mode.py Adds persisted floorplan mode override behavior + tamper checks.
agent/test/test_floorplan_mode_rerun.py Exercises floorplan-mode-only reruns and resume behavior end-to-end.
agent/test/test_engine.py Moves agent resume regression test into agent engine tests; adds candidate snapshot suppression test.
agent/test/test_candidate_resume.py Adds candidate resume validation and in-place resume execution behavior tests.
agent/test/data/test_candidate_materialization.py Tightens materialization to one-knob patches and adds snapshot/receipt validation tests.
agent/test/data/test_candidate_input_binding.py Extends canonical edges and allows Floorplan-from-Synthesis (verilog-only) binding.
agent/sta_parallel.py Implements candidate-only parallel STA execution with isolated worker processes.
agent/sta_benchmark.py Adds a CLI benchmark tool to compare serial vs parallel STA schedules on isolated workspace copies.
agent/server.py Ensures agent environment prep at startup and maps request validation errors to JSON-RPC invalid_request.
agent/runtime_env.py Adds packaged Sizer PATH injection, Sizer+DREAMPlace preflight, and LD_* isolation context manager.
agent/rpc_server.py Implements minimal ecc-agent-rpc stdio entrypoint.
agent/requests.py Adds new request models/fields for agent preflight and candidate resume/rerun binding.
agent/README.cn.md Documents the ecc-agent-rpc entrypoint, protocol constraints, and maintenance expectations (CN).
agent/plot.py Adds candidate workspace detection and plot suppression/headless map plotting controls.
agent/methods.py Registers new agent RPC methods (agent.runtime_preflight, candidate.resume).
agent/floorplan_mode.py Implements persisted, tamper-evident floorplan mode overrides for candidates.
agent/engine.py Adds observer notifications, stdout redirect locking, candidate snapshot suppression, and STA memory tracking.
agent/data/parameter_runtime_observer.py Implements DREAMPlace/floorplan parameter observation and v2 runtime report persistence.
agent/data/parameter_application_receipt.py Produces v2 parameter application receipts with stable evidence hashing.
agent/data/observed_callable.py Utility wrapper to preserve operator attributes while intercepting call behavior.
agent/data/floorplan_parameter_observer.py Adds floorplan parameter observation and v2 report generation.
agent/data/candidate_materialization.py Enforces single-knob patches and binds config overlays via immutable snapshots + receipt validation.
agent/data/candidate_input_binding.py Expands canonical input edges and loosens DEF requirement for Synthesis source.
agent/candidate_resume.py Implements resume of failed candidates with strict binding/rollback and structured failure results.
agent/candidate_clone.py Implements safe candidate workspace cloning with step artifact pruning.
.gitignore Ignores top-level checklist.json.
.github/actions/build-pyinstaller-bundle/action.yml Extends PyInstaller smoke test to validate ecc-agent-rpc presence, aliasing, and capability output.
Review details
  • Files reviewed: 51/52 changed files
  • Comments generated: 2
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread agent/workspace_api.py
Comment on lines +867 to +883
tech_lef = Path(getattr(getattr(workspace, "pdk", None), "tech", None))
pdk_sha256 = f"sha256:{sha256(tech_lef.read_bytes()).hexdigest()}"
lef_text = tech_lef.read_text(encoding="utf-8")
units_match = re.search(r"DATABASE\s+MICRONS\s+(\d+)", lef_text, re.IGNORECASE)
site_match = re.search(
r"SITE\s+(?:core7|CoreSite)\b(?P<body>.*?)END\s+(?:core7|CoreSite)",
lef_text,
re.IGNORECASE | re.DOTALL,
)
size_match = re.search(
r"SIZE\s+([0-9]+(?:\.[0-9]+)?)\s+BY",
site_match.group("body") if site_match else "",
re.IGNORECASE,
)
if not units_match or not size_match:
raise ValueError("site width is unavailable")
site_width_dbu = round(float(units_match.group(1)) * float(size_match.group(1)))

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Updated in commit 8474449. _parameter_receipt_context now uses workspace.pdk.site_core with re.escape(...) to locate the LEF SITE block instead of hard-coded site names.

Comment thread agent/test/test_parameter_receipt_artifacts.py Outdated
YihangQiu and others added 6 commits September 9, 2026 19:08
The ECC C++ tools keep process-global config and log state, so two
candidates executing inside one rpc-server process cross-write logs and
leave steps Incomplete. Each candidate rerun/resume now executes its step
loop in a dedicated worker subprocess; the parent keeps the operation
lifecycle and replays step.started events from the worker result. Unit
tests drive the in-process path via ECC_CANDIDATE_STEP_ISOLATION=0;
isolated execution falls back in-process when no interpreter is
available.
normalize_design ran opt_clean -purge, stripping internal public net names
so equiv_make only matched top-level ports and equiv_induct lacked internal
cut-points, producing mass unproven results on functionally equivalent
netlists. Drop -purge on the normalize side; the equiv-side purge stays.

Same root cause and fix as upstream a6217b9a (ecc#273).
Co-authored-by: YihangQiu <65992277+YihangQiu@users.noreply.github.com>
sta_workers() gated parallel corners on candidate workspaces only, so
GUI flows ran the sta step serially while optimization candidates ran
in parallel. The corner snapshot mechanism is a generic ECC facility
(each worker loads its own file snapshot), so drop the workspace gate
and keep the tool/step, worker-count, and platform checks.
ECOS_AGENT_STA_WORKERS (default 2 on Linux) now applies to every
agent-runtime sta step.
…ment

- ecc-dreamplace efbca335..er 77e343ca (v0.1.0-alpha.6-10): macro-only
  placement writeback; requires the ECC-side macro placement parameter
  plumbing arriving with the upstream main merge.
- ecc-tools efbca335..fdaa70a97 (v0.1.0-alpha.13-269): requires
  Boost 1.92.0 exactly (built against /home/yhqiu1/.deps/boost-1.92.0,
  the upstream CI recipe).
Brings in upstream main through 0d2b176: ECC QoR v3 analysis engine,
DreamPlace macro placement step (pairs with ecc-dreamplace 77e343ca),
manual macro location flow, lec disabled by default (yosys lec
instability), yosys synthesis flag fixes, and sizer/routing-STA crash
diagnostics. One test conflict resolved by keeping both the local
random_seed fixture and upstream's macro_only key.
The candidate input-edge allowlist still assumed the single-step
Floorplan topology, so every isolated candidate rerun failed at
bind_candidate_input with 'unsupported candidate input edge:
postFloorplan -> place' before any step could execute, leaving
candidate workspaces without analysis artifacts and forcing every
optimization outcome to evidence_invalid.

Declare the current canonical edges for the preFloorplan ->
macroPlacement -> postFloorplan phase split (and the tail steps it
introduced), resolve the RPC-level Floorplan target to the sub-step
range with the Synthesis checkpoint as its source, and cover the
current topology with regression tests.
Floorplan-knob candidate reruns failed in three places that still
assumed a literal Floorplan flow step: the step-range lookup, the
input-binding target resolution, and the candidate-backend tool check.
Resolve the RPC-level Floorplan target through a shared
FLOORPLAN_TARGET_FLOW_STEP alias with a literal-name fallback.

With the aliases in place the rerun exposed the real blocker: the
floorplan runner re-pins '[params.die] size' with the realized die
bounding box after every floorplan step, and _refresh_floorplan_config
forces die_builder.mode back to die_size whenever that pin exists, so
a die_util candidate was always reverted and rejected by the terminal
mode validation. Treat the realized dimensions as outputs: the runner
re-pins the size only in die_size workspaces, and die_util candidates
drop the pin in their isolated clone before the flow loads parameters.

Verified end to end on a gcd workspace clone: a floorplan.core_util
0.3 -> 0.4 candidate at die_util now runs all 16 steps, keeps the
die_util mode, and realizes core_area 2381.4 -> 1796.76 um^2.
# Conflicts:
#	agent/engine.py
#	chipcompiler/runtime/operations.py
@YihangQiu
YihangQiu requested a lite review from Copilot September 16, 2026 02:55

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants