skills/pdh-locking/SKILL.md
Use this skill whenever interacting with the PDH (Pound-Drever-Hall) optical cavity locking FastAPI service running at http://127.0.0.1:8001. Triggers include: any request to calculate PI, query task results, check or control lock state, set PID/modulation parameters, export waveforms, or monitor power. Also use when user mentions "PDH", "Pound-Drever-Hall", "lock", "锁定", "PI calculation", "task ID", "/pi/", "/lock/", "/pid/", "/modulation/", "/plot/", "/power/" endpoints. Do NOT use for general FastAPI services unrelated to PDH locking.
npx skillsauth add Plan1014/LabPilot pdh-lockingInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Controls a PDH (Pound-Drever-Hall) optical cavity locking system via FastAPI at
http://127.0.0.1:8001. The service wraps a PyQt5 GUI control panel and
executes operations in the main GUI thread via a thread-safe command queue.
http://127.0.0.1:8001
All commands use curl.exe on Windows (PowerShell/cmd compatible).
| Operation | Method | Endpoint | Notes |
| --------- | ------ | ------------------- | ---------------------------------------------- |
| PI 计算 | POST | /pi/calculate | Returns task_id, result pushed via WebSocket |
| 查询结果 | GET | /task/{task_id} | 仅在用户明确要求时查询 |
| 锁定状态 | GET | /lock/status | Returns {"locked": bool} |
| 执行锁定 | POST | /lock/manual | Triggers lock — verify with power check |
| 执行解锁 | POST | /lock/stop | Returns {"status": "stopped"} |
| 设置 PID | POST | /pid/set | {"kp":0-8191,"ki":0-8191,"kd":0-8191} |
| 设置调制 | POST | /modulation/set | {"frequency_mhz":0-99,"amplitude_vpp":0-2} |
| 导出波形 | POST | /plot/export | {"save_path":"*.png"} |
| 读取功率 | GET | /power/monitor | Returns power snapshot |
When PI calculation completes, the result is automatically pushed to the agent via the NotificationHub (port 8000). You do NOT need to poll for results.
The push notification format:
[WebSocket] task_completed: P={value}, I={value}
For example:
[WebSocket] task_completed: P=1800, I=4800
Important: When you receive such a WebSocket notification, report the result to the user. Do NOT initiate additional PI calculations unless the user explicitly requests it.
⚠️ Important constraints:
Execution flow:
curl.exe -X POST http://127.0.0.1:8001/pi/calculate
Response (immediate):
{"task_id": "uuid-string", "status": "pending"}
Tell the user "PI calculation started", then end immediately.
Do NOT wait for results, do NOT spawn subagents, do NOT poll /task/{task_id}.
Why: Results are automatically pushed via WebSocket when complete. When you receive a message in this format:
[WebSocket] task_completed: P={value}, I={value}
It means the result has arrived and this agent will be triggered again to report the result. You do NOT need to do anything else.
Forbidden behaviors:
/task/{task_id}The system handles result delivery automatically.
⚠️ Critical: Lock state vs actual lock verification
The /lock/status endpoint returns {"locked": bool} which reflects the
software lock flag (panel.parameters.lock.value). A successful HTTP
response from /lock/manual does NOT guarantee the physical lock succeeded.
Always verify lock success with a power comparison:
/lock/manual, call /power/monitor and record power_before/lock/manual/power/monitor → power_afterpower_after < power_before (power dropped), the lock is successfulpower_after >= power_before, the lock may have failed — report thisCheck lock status:
curl.exe http://127.0.0.1:8001/lock/status
Execute lock:
curl.exe -X POST http://127.0.0.1:8001/lock/manual
Execute unlock (stop lock):
curl.exe -X POST http://127.0.0.1:8001/lock/stop
Returns: {"status": "stopped", "message": "Lock successfully stopped"}
PID values are integers in range 0–8191 (inclusive).
curl.exe -X POST http://127.0.0.1:8001/pid/set ^
-H "Content-Type: application/json" ^
-d "{\"kp\":100,\"ki\":50,\"kd\":10}"
Response: {"status": "updated", "kp": 100, "ki": 50, "kd": 10}
Parameters:
kp — proportional gain (0–8191)ki — integral gain (0–8191)kd — derivative gain (0–8191)curl.exe -X POST http://127.0.0.1:8001/modulation/set ^
-H "Content-Type: application/json" ^
-d "{\"frequency_mhz\":10.5,\"amplitude_vpp\":1.2}"
Response: {"status": "updated", "freq_mhz": 10.5, "amp_vpp": 1.2}
Parameters:
frequency_mhz — float, range 0–99 MHzamplitude_vpp — float, range 0–2 Vpp⚠️ Frequency warnings (inform the user):
> 10 MHz: Signal begins to distort — warn the user> 31.25 MHz: Signal is completely unusable — strongly warn the usercurl.exe -X POST http://127.0.0.1:8001/plot/export ^
-H "Content-Type: application/json" ^
-d "{\"save_path\":\"spectrum.png\"}"
Default path is spectrum.png if save_path is omitted.
curl.exe http://127.0.0.1:8001/power/monitor
Returns the current power reading snapshot. Use this for lock verification as described in the Lock Control section.
| Scenario | HTTP Status | Response |
| ---------------- | ----------- | ------------------------------------------- |
| Success | 200 | JSON with result data |
| Not found | 404 | {"detail": "Task not found or expired"} |
| Validation error | 422 | {"detail": [...]} |
For async tasks (/pi/calculate):
{"task_id": "...", "status": "pending"}"Calculate PI and give me the result" → Verify system is unlocked (if locked, unlock it) → POST /pi/calculate → get task_id → Tell the user "PI calculation started", then end immediately. If WebSocket push arrives → report result
"Is the PDH system locked?" → GET /lock/status → report locked state
"Lock the system" → GET /power/monitor → store power_before → POST /lock/manual → → GET /power/monitor → compare → report success/failure
"Set kp=200, ki=75, kd=15" → POST /pid/set with those values → confirm update
"Set modulation to 15 MHz" → Warn about distortion above 10 MHz → POST /modulation/set → confirm
"Set modulation to 35 MHz" → Warn that >31.25 MHz is completely unusable → ask user to confirm
"Export the waveform to wave.png" → POST /plot/export with save_path="wave.png" → confirm file saved
"What's the current power?" → GET /power/monitor → report value
development
Use this skill whenever the user wants to create a new SKILL.md file, design a reusable workflow, or package instructions for Claude to follow. Triggers include: "帮我创建一个技能", "create a new skill", "我想添加一个新的 XX 技能", "make this a skill", "create a skill for X", "turn this into a reusable skill". This skill helps users design, brainstorm, and generate new skills through interactive guidance, following the official SKILL.md anatomy guidelines. Do NOT use for general conversations unrelated to skill creation.
documentation
Parse and analyze academic papers from PDF files, generate structured JSON summaries and save to docs/papers directory.
development
Controls the Rohde & Schwarz Phase Noise Analyzer via REST API. Use this skill when the user wants to measure phase noise, start PNA sweeps, check instrument health, or read frequency-domain data. Triggers include: "PNA", "phase noise", "sweep", "measure noise", "start measurement", "/measure/", "/health/". Also use when user mentions "Rohde & Schwarz", "spectrum", "PNR", or asks about "carrier suppression", "SSB phase noise". Do NOT use for general network requests unrelated to PNA instruments.
development
Maintainer-only workflow for handling GitHub Secret Scanning alerts on OpenClaw. Use when Codex needs to triage, redact, clean up, and resolve secret leakage found in issue comments, issue bodies, PR comments, or other GitHub content.