From rtl-agent-team
Auto-loops DC-based PPA optimization on RTL designs by repeating rtl-ppa-optimize-dc until convergence, early plateau, or max cycles. Includes 30-min auto-continue and final verification.
npx claudepluginhub babyworm/rtl-agent-team --plugin rtl-agent-teamThis skill is limited to using the following tools:
<Purpose>
Generates design tokens/docs from CSS/Tailwind/styled-components codebases, audits visual consistency across 10 dimensions, detects AI slop in UI.
Records polished WebM UI demo videos of web apps using Playwright with cursor overlay, natural pacing, and three-phase scripting. Activates for demo, walkthrough, screen recording, or tutorial requests.
Delivers idiomatic Kotlin patterns for null safety, immutability, sealed classes, coroutines, Flows, extensions, DSL builders, and Gradle DSL. Use when writing, reviewing, refactoring, or designing Kotlin code.
<Use_When>
<Do_Not_Use_When>
/rtl-agent-team:rat-ultraloop-ppa [top_module]
import json, time, shutil, subprocess, pathlib
TOP = ARGUMENTS or json.load(open("requirements.json"))["top_module"]
# Hard preconditions
assert shutil.which("dc_shell") or shutil.which("genus"), \
"rat-ultraloop-ppa requires dc_shell or genus in PATH"
req = json.load(open("requirements.json"))
assert "ppa_targets" in req, \
"requirements.json missing ppa_targets — run rtl-ppa-optimize-dc once to scaffold"
max_cycles = int(req["ppa_targets"].get("convergence", {}).get("max_cycles", 4))
# Initialize state
state_path = pathlib.Path(".rat/state/ppa-loop-state.json")
if not state_path.exists():
state = {
"mode": "ppa-loop",
"cycle": 0,
"max_cycles": max_cycles,
"weights": req["ppa_targets"].get("weights", {"timing":0.7, "power":0.2, "area":0.1}),
"convergence": {
"delta_pct": req["ppa_targets"].get("convergence", {}).get("delta_pct", 2.0),
"streak_required": req["ppa_targets"].get("convergence", {}).get("streak", 3),
"early_plateau_pct": req["ppa_targets"].get("convergence", {}).get("early_plateau_pct", 1.0),
"history": [],
},
"allowed_edit_scope": [f"rtl/{TOP}/**/*.sv"],
"frozen_scope": ["rtl/common/**", "rtl/pkg/**", "rtl/intf/**"],
"last_cycle_timestamp": int(time.time()),
"auto_continue_minutes": 30,
}
state_path.parent.mkdir(parents=True, exist_ok=True)
state_path.write_text(json.dumps(state, indent=2))
# The LLM executes the following iterative protocol. The block below is
# CONCEPTUAL pseudo-code (Skill() is not a callable Python function) —
# the real mechanism is a slash-command invocation followed by reading
# the verdict file that the orchestrator writes.
For each cycle in 1..max_cycles:
/rtl-agent-team:rtl-ppa-optimize-dc <TOP>.
This runs exactly one PPA iteration via the orchestrator, which writes
docs/ppa-opt/iter-{cycle}/verdict.txt on completion.1a. Refresh auto-continue timestamp — update last_cycle_timestamp in
.rat/state/ppa-loop-state.json to the current epoch seconds BEFORE
invoking rtl-ppa-optimize-dc. This ensures the 30-minute
stop-gate.sh window restarts each cycle, not only at loop start.
```python
import json, time, pathlib, os, tempfile, fcntl
STATE_PATH = pathlib.Path(".rat/state/ppa-loop-state.json")
LOCK_PATH = str(STATE_PATH) + ".lock"
with open(LOCK_PATH, "a") as lock_f: # long-lived lock file; never replaced
fcntl.flock(lock_f.fileno(), fcntl.LOCK_EX)
try:
s = json.loads(STATE_PATH.read_text())
s["last_cycle_timestamp"] = int(time.time())
dir_ = STATE_PATH.parent
fd, tmp = tempfile.mkstemp(prefix=".ppa-state-", dir=str(dir_))
try:
with os.fdopen(fd, "w") as tmp_f:
json.dump(s, tmp_f, indent=2)
os.replace(tmp, str(STATE_PATH)) # atomic swap
except BaseException:
try:
os.unlink(tmp)
except OSError:
pass
raise
finally:
fcntl.flock(lock_f.fileno(), fcntl.LOCK_UN)
```
Uses the same atomic lock-file + `os.replace()` pattern as `compute_delta.py`:
a `.lock` file is held via `fcntl.flock` during the read-modify-write cycle,
and the updated state is written to a temp file then atomically renamed
onto the canonical path. This prevents `stop-gate.sh` from observing a
truncated state file between steps.
2. Read verdict — read docs/ppa-opt/iter-{cycle}/verdict.txt. Expected
values: CONTINUE, CONVERGED_STREAK, CONVERGED_TARGETS, EARLY_PLATEAU,
MAX_CYCLES, TIMING_REGRESSION.
Dispatch by verdict:
CONVERGED_STREAK or CONVERGED_TARGETS:
/rtl-agent-team:rtl-p5-verify --mode=final --source=ppa-opt
for full regression confirmation..rat/state/rtl-verify-done with ppa-opt-converge cycle {cycle}\n..rat/state/ppa-opt-done with converge cycle {cycle}\n (triggers
P6 cascade re-review if the design-note was written prior).docs/ppa-opt/final-report.md (see template below)..rat/state/ppa-loop-state.json.EARLY_PLATEAU:
reviews/ppa-opt/early-plateau-escalation.md..rat/state/ppa-loop-state.json.MAX_CYCLES:
docs/ppa-opt/final-report.md with exit_reason MAX_CYCLES
(best-so-far iteration recorded)..rat/state/ppa-loop-state.json.TIMING_REGRESSION:
git checkout -- rtl/<top>.reviews/ppa-opt/timing-regression-escalation.md..rat/state/ppa-loop-state.json.CONTINUE:
Safety net — if the loop falls through max_cycles without a terminal
verdict (should not happen), generate final-report with exit_reason
LOOP_EXIT_UNEXPECTED and remove the state file.
Note: The per-cycle refresh of
last_cycle_timestamp(step 1a) is critical:stop-gate.shuses it to decide whether the 30-min auto-continue window is still active. Without it, long DC iterations would be interrupted 30 minutes after loop start even when the loop is making progress.
docs/ppa-opt/final-report.md)# PPA Optimization Final Report
- Target module: {TOP}
- Cycles executed: {N} / {max_cycles}
- Exit reason: CONVERGED | EARLY_PLATEAU | MAX_CYCLES
## Iteration history
| iter | wns_ns | power_mw | area_um2 | weighted_Δ |
## Best-so-far iteration
- iter: {best_iter}
- wns_ns: {} power_mw: {} area_um2: {}
## Next steps
- If CONVERGED: full Phase 5 regression passed → proceed to Phase 6 design note
- If EARLY_PLATEAU: see reviews/ppa-opt/early-plateau-escalation.md
- If MAX_CYCLES: consider raising max_cycles in requirements.json["ppa_targets"]["convergence"]
Reuses the stop-gate.sh escalation pattern: when
.rat/state/ppa-loop-state.json is present with mode == "ppa-loop" and
last_cycle_timestamp + auto_continue_minutes*60 > now, the hook auto-continues
instead of stopping.