--- description: > Antigravity development mode rules. Apply when the user requests high-speed iteration, a quick prototype, or says "反重力开发" / "antigravity mode". globs: "plugins/**/*.py" always_on: false --- # Antigravity Development Mode > High-speed delivery + strict reversibility. Every decision must keep both roll-forward and rollback feasible. --- ## Core Principles 1. **Small, isolated edits** — one logical change per operation; no mixing refactor + feature. 2. **Deterministic interfaces** — function signatures and return shapes must not change without an explicit contract update. 3. **Multi-level fallback** — every I/O path has a degraded alternative (e.g., S3 → local → DB). 4. **Reversible by default** — every file write, API call, or schema change must have an undo path recorded or be idempotent. --- ## Mandatory Safety Patterns ### 1. Timeout Guards on All Frontend Calls Any `__event_call__` or `__event_emitter__` JS execution MUST be wrapped: ```python import asyncio try: result = await asyncio.wait_for( __event_call__({"type": "execute", "data": {"code": js_code}}), timeout=2.0 ) except asyncio.TimeoutError: logger.warning("Frontend JS execution timed out; falling back.") result = fallback_value except Exception as e: logger.error(f"Frontend call failed: {e}", exc_info=True) result = fallback_value ``` JS side must also guard internally: ```javascript try { return (localStorage.getItem('locale') || navigator.language || 'en-US'); } catch (e) { return 'en-US'; } ``` ### 2. Path Sandbox Validation Resolve every workspace path and verify it stays inside the repo root: ```python import os def _validate_workspace_path(path: str, workspace_root: str) -> str: resolved = os.path.realpath(os.path.abspath(path)) root = os.path.realpath(workspace_root) if not resolved.startswith(root + os.sep) and resolved != root: raise PermissionError(f"Path escape detected: {resolved} is outside {root}") return resolved ``` ### 3. Dual-Channel Upload Fallback Always try API first; fall back to DB/local on failure: ```python async def _upload_file(self, filename: str, content: bytes) -> str: # Channel 1: API upload (S3-compatible) try: url = await self._api_upload(filename, content) if url: return url except Exception as e: logger.warning(f"API upload failed: {e}; falling back to local.") # Channel 2: Local file + DB registration return await self._local_db_upload(filename, content) ``` ### 4. Progressive Status Reporting For tasks > 3 seconds, emit staged updates: ```python await self._emit_status(emitter, "正在分析内容...", done=False) # ... phase 1 ... await self._emit_status(emitter, "正在生成输出...", done=False) # ... phase 2 ... await self._emit_status(emitter, "完成", done=True) ``` Always emit `done=True` on completion and `notification(error)` on failure. ### 5. Emitter Guard Check before every emit to prevent crashes on missing emitter: ```python if emitter and self.valves.SHOW_STATUS: await emitter({"type": "status", "data": {"description": msg, "done": done}}) ``` ### 6. Exception Surface Rule Never swallow exceptions silently. Every `except` block must: - Log to backend: `logger.error(f"...: {e}", exc_info=True)` - Notify user: `await self._emit_notification(emitter, f"处理失败: {str(e)}", "error")` --- ## Edit Discipline | ✅ DO | ❌ DO NOT | |-------|-----------| | One function / one Valve / one method per edit | Mix multiple unrelated changes in one operation | | Validate input at the function boundary | Assume upstream data is well-formed | | Return early on invalid state | Nest complex logic beyond 3 levels | | Check fallback availability before primary path | Assume primary path always succeeds | | Log before and after expensive I/O | Skip logging for "obvious" operations | --- ## Rollback Checklist Before completing an antigravity operation, confirm: - [ ] No global state mutated on `self` (filter singleton rule) - [ ] File writes are atomic or can be recreated - [ ] Database changes are idempotent (safe to re-run) - [ ] Timeout guards are in place for all async calls to external systems - [ ] The user can observe progress through status/notification events - [ ] Non-obvious findings / gotchas are saved to `.agent/learnings/{topic}.md` --- ## Mandatory: Knowledge Capture Any non-obvious pattern, internal API contract, or workaround discovered during an antigravity session **MUST** be saved to `.agent/learnings/{topic}.md` before the session ends. This ensures hard-won insights are not lost between sessions. **Format**: See `.agent/learnings/README.md` **Existing entries**: Browse `.agent/learnings/` for prior knowledge to reuse. --- ## References - Full engineering spec: `.github/copilot-instructions.md` → Section: **Antigravity Development Mode** - Design document: `docs/development/copilot-engineering-plan.md` → Section 5 - Knowledge base: `.agent/learnings/` — reusable engineering patterns and gotchas