Files
planet/rules.md
linkong fbecf30513
Some checks failed
ci / backend (push) Has been cancelled
ci / frontend (push) Has been cancelled
ci / delivery (push) Has been cancelled
release / images (push) Has been cancelled
release: bump version to 0.73.0
2026-06-29 17:04:05 +08:00

568 lines
23 KiB
Markdown

---
name: planet-rules
description: Planet repository rules split into LLM-loadable modules.
---
# Planet Rules
**These rules are mandatory. If a requested action conflicts with this file, stop and report the conflict.**
## Loading Protocol
Read this top section first, then load only the modules relevant to the task.
Always load:
- `core`
- `security`
- `workflow`
Load selectively:
| Module | Load when |
|--------|-----------|
| `docs` | Writing, translating, linking, or publishing documentation |
| `uiux` | Visual design, layout, interaction, accessibility, responsive behavior |
| `frontend` | React, TypeScript, CSS, Vite, Bun, admin console, docs UI |
| `backend` | FastAPI, SQLAlchemy, data collectors, database, API performance |
| `earth` | 3D Earth, canvas/Three.js, BGP/vessel/satellite/cable layers, map icons |
| `ai` | AI Provider, LLM gateway, prompts, model config, AI Playground |
| `release` | Version bumps, changelog, version history, commit/tag/push release work |
Do not load the entire file by default for small tasks. Use `rg -n "^## Module:" rules.md` to find module boundaries, then read only the needed block.
### Agent Discovery Index
Use these shortcuts when the user describes work in product language instead of
module names. Matching one of these phrases means the related module is
relevant, even if the exact module name is not mentioned.
| User wording / touched surface | Load modules |
| --- | --- |
| `一屏`, `首屏`, `高度没控住`, page grows past viewport, scroll/overflow, spacing/breathing, responsive, accessibility | `uiux`, `frontend` |
| Admin console, 控制台, sidebar/menu/search/tabs/dialog/table, theme/language switch, i18n, auth pages, public Docs UI | `frontend`, plus `uiux` for rendered/layout changes |
| Docs, 文档, 中英文, public Docs, manual, quickstart, README, plan status, stale route/section links | `docs`, plus the implementation module for the changed behavior |
| API, FastAPI, database, SQLAlchemy, collector, datasource, scheduler, credential/connectivity, pagination, slow endpoint | `backend` |
| Earth/地球, 3D/canvas/Three.js, BGP/vessel/satellite/cable, terrain/clouds, marker/icon, hover/lock/tooltip, flicker/z-fighting | `earth`, plus `uiux` for visible controls |
| AI Provider, model provider, Playground, prompt, mapping, custom collector, base URL, service token, OCR/WebSearch/Tavily integration | `ai`, plus `security` for credentials |
| Version/changelog/history/tag/release, `发版`, `发布`, `打包`, `版本号`, commit/push release work | `release`, `workflow` |
| Secrets, `.env`, API key, token, password, credential masking, auth/JWT/logout, logs containing sensitive data | `security`, plus touched implementation module |
| Dependency/package-manager/tooling, Bun/uv, npm/pnpm/yarn, lockfiles, dirty worktree, generated output | `workflow` |
---
## Module: core
### Load When
Always.
### Must
- Keep functions small and focused; one concern per file/module.
- Write self-documenting code; comments explain why, not what.
- Prefer dependency injection for testability.
- Use feature flags for incomplete features.
- Use config files or environment variables for environment-specific settings.
- Maintain one source of truth for business state. Temporary UI state, cached state, and persisted backend state must not become parallel truths.
- Transitional paths are temporary. Once a new implementation is stable, remove old branches, old interfaces, old mocks, and compatibility layers.
- Extract repeated request flow, response handling, auth/header assembly, validation, and state reconciliation into helpers or shared layers.
- Centralize default values, system prompts, placeholder structures, and fixed constants.
- Public interfaces, persisted fields, and state structures must have a current owner and caller. Delete unused ones.
- After large feature work, run an explicit cleanup pass for dead code, duplicated helpers, stale interfaces, and naming drift.
### Code Style
- Python: 4-space indentation, Black style, max line length 100.
- TypeScript: 2-space indentation, Prettier style, max line length 100.
- No trailing whitespace.
- Empty line at end of file.
- Sort imports alphabetically inside groups.
- Never use wildcard imports.
- Avoid unclear abbreviations except common ones such as `id`, `ok`, `err`.
- Prefer descriptive names.
- Keep functions around 50 lines or less where practical.
- Split files before they become mixed-responsibility modules.
### Import Order
Python:
```python
# stdlib -> third-party -> local
import json
from datetime import datetime
from fastapi import APIRouter
from sqlalchemy.orm import Session
from app.core.config import settings
```
TypeScript:
```typescript
// React -> third-party -> local
import { useEffect, useState } from 'react'
import axios from 'axios'
import { api } from '@/services/api'
```
### Type Rules
- Use type hints throughout Python.
- Define TypeScript interfaces/types for all structured data.
- Avoid `Any`; use specific unions, generics, or `unknown` where appropriate.
- Prefer typed helpers over repeated type casting.
### Verify
- Use deterministic checks before broad manual inspection:
```bash
git diff --check
rg -n "TODO|FIXME|console\.log|debugger|print\(" <changed-paths>
```
---
## Module: security
### Load When
Always.
### Must
- Never commit `.env`, secrets, keys, tokens, or credentials.
- Use environment variables or the configured settings store for credentials.
- Validate and sanitize user input.
- Use parameterized database queries.
- Never store plain-text passwords.
- Hash passwords with bcrypt/argon2.
- Use short-lived JWT tokens when auth tokens are involved.
- Use token blacklist or equivalent revocation support for logout.
- Do not expose full tokens in UI. Show only a short prefix and mask the rest.
### Verify
```bash
git diff --name-only HEAD
rg -n "api[_-]?key|client_secret|BEGIN .*PRIVATE KEY|AKIA[0-9A-Z]" .
```
---
## Module: workflow
### Load When
Always.
### Git
- Do not revert user changes unless explicitly requested.
- Do not force push to protected branches.
- Use clear commit messages.
- Run relevant tests and builds before committing.
- Frontend package management must use Bun only.
- Never use `npm`, `pnpm`, or `yarn` in the frontend project.
- Verify package legitimacy before adding dependencies.
- Prefer maintained, widely used libraries.
- Pin dependency versions in `pyproject.toml`, `uv.lock`, and `package.json`.
### Deterministic Context
- Prefer compact CLI evidence over reading large files or full diffs:
```bash
git status --short
git diff --stat HEAD
git diff --name-only HEAD
git diff --unified=0 HEAD -- <path>
rg -n "<pattern>" <path>
```
---
## Module: docs
### Load When
Writing, translating, linking, restructuring, or publishing docs.
Also load this module when the user mentions docs in Chinese or product terms:
`文档`, `中英文`, `双语`, `public Docs`, `手册`, `quickstart`,
`README`, `计划`, `plan`, `过期说明`, `路由文档`, `section 链接`,
or asks to make rules easier to discover.
### Must
- Chinese docs under `docs/technical/zh/` must be Chinese prose, not copied English placeholders.
- Keep technical identifiers, API paths, config keys, code symbols, and product names in English where appropriate.
- Explain why a change exists, not only what files changed.
- Prefer updating an existing relevant doc over creating a duplicate.
- Use `##` and `###` headings; avoid going deeper than three levels.
- Use fenced code blocks with language tags.
- Use tables when comparing options or listing parameters.
- Do not reference PR numbers, issue numbers, or the current conversation.
- Internal links inside `docs/technical/zh/` should point to `docs/technical/zh/...` unless intentionally linking to English-only docs.
- Public Docs UI must only expose documents explicitly registered in `frontend/src/pages/Docs/docs-content.ts`.
- Development plans and task notes under `docs/plans/` are not automatically public documentation.
### Required Content
- Background/problem.
- Core design decisions and rationale.
- Key snippets or focused examples.
- Related files and each file's role.
- Operational caveats or verification steps when relevant.
### Verify
```bash
git diff --stat HEAD
git diff --name-only HEAD
ls docs/technical/zh/
rg -n "\]\(([^)]+)\)" docs/technical/zh/<doc>.md
rg -n "/home/ray/dev/linkong/planet/docs/technical/(?!zh|en)" docs/technical/zh --pcre2
```
Check zh/en duplicates:
```bash
python - <<'PY'
from pathlib import Path
same = []
for en in sorted(Path("docs/technical/en").glob("*.md")):
zh = Path("docs/technical/zh") / en.name
if zh.exists() and en.read_text() == zh.read_text():
same.append(en.name)
if same:
raise SystemExit("identical en/zh docs: " + ", ".join(same))
print("no identical en/zh docs")
PY
```
---
## Module: uiux
### Load When
Changing layout, visual hierarchy, controls, interaction states, responsive behavior, or accessibility.
Also load this module when the user mentions Chinese layout terms such as
`一屏`, `首屏`, `高度没控住`, `页面撑出`, `滚动`, `溢出`, `呼吸感`,
`间距`, or `响应式`.
### Hard Rule: Admin One-Screen Workspaces
Backend/admin pages are compact single-screen workspaces (`一屏` / `首屏`):
- The route shell must resolve to the viewport through the existing
`html`, `body`, `#root`, route-root, and page-shell `height: 100%` chain.
- Intermediate shell nodes such as theme providers must not break the height
chain; they need `height: 100%`, `min-height: 0`, and explicit overflow
ownership when they wrap the page shell.
- Header, summary/controls, main work area, and fixed sidebar account/actions
must remain inside the first viewport on common desktop sizes.
- Long menus, tables, detail panels, logs, Markdown, JSON, and forms scroll
inside their intended region; the document/body/root must not become the
scroll owner.
- A build is not enough for height-critical changes. Use rendered validation
on the affected admin routes, and include 125% / 150% zoom when the change
touches shell, sidebar, panel, table, or scroll ownership.
### Must
- Backend/admin pages are single-screen workspaces first, not long landing pages.
- Common desktop viewports should show the page header, summary/controls, and main work area.
- The main work area gets most available height.
- If text, controls, or tables become unreadable, give that region an internal scrollbar instead of crushing it.
- Overflow ownership must be explicit:
- parent height chain is valid
- height-constrained flex parents use `min-height: 0`
- only the intended scroll node owns `overflow: auto`
- Do not use `overflow: hidden` as a final fix unless another child owns scrolling.
- Tabs define their own scroll strategy; hidden panes must stay hidden.
- Long-form content such as AI briefs, logs, Markdown, raw JSON, and help text should stay readable.
- Prefer stable readable minimum heights plus scrolling for constrained content.
- Avoid brittle `100vh/100vw` in embedded/admin shells; prefer `height: 100%` chains.
- Verify layouts under browser zoom 125% and 150% when changing height-critical screens.
- Avoid wrapper components with implicit layout behavior, such as `Space`, in height-critical scroll regions unless the generated DOM is accounted for.
- Any UI state that hides data or a layer must also reconcile hover, lock, tooltip, and selection state.
### Visual Controls
- Use icons in buttons for common tools/actions when an established icon exists.
- Keep icon-only buttons accessible with `aria-label` and `title`.
- Use segmented controls for modes, switches/checkboxes for binary settings, sliders/inputs for numeric values, menus/selects for option sets, and tabs for views.
- Connection-test actions for endpoint/Base URL inputs must use the shared `ConnectionTestInput` pattern: a single plug/connector icon at the input suffix, no adjacent text button; disabled integrations should grey out the field and its test action.
- Do not put cards inside cards.
- Do not use visible in-app text to explain obvious UI features or styling.
- Text must fit within its parent on mobile and desktop.
- Do not scale font size with viewport width.
- Letter spacing should usually be `0`.
### Verify
```bash
changed=$(git diff --name-only HEAD -- frontend/src)
[ -z "$changed" ] || rg -n "overflow|min-height|Space|Tabs|aria-label|title=" $changed
```
---
## Module: frontend
### Load When
Editing React, TypeScript, CSS, Vite, Bun, admin console, public Docs UI, or client-side services.
Also load this module when the user mentions `控制台`, `Admin`, `Docs 页面`,
`登录/注册/忘记密码`, `i18n`, `语言切换`, `主题切换`, `搜索`, `菜单`,
`Tab`, `弹窗`, `表格`, `Markdown`, frontend build, or any file under
`frontend/src`.
### Must
- Use Bun for frontend commands:
```bash
bun install
bun run --cwd frontend build
```
- Never use `npm`, `pnpm`, or `yarn`.
- Keep shared behavior in reusable components/services, not page-local copies.
- Prefer existing project components and patterns.
- Keep page state, backend state, and persisted state clearly separated.
- Presentation state must not pretend to be business state.
- Loading, error, stopped, retry, edit, and view states need explicit semantics.
- Responsive adaptations must preserve the primary action path.
- Markdown rendering behavior belongs in the shared Markdown renderer, not individual docs.
- Public Docs navigation must be whitelist-driven through metadata, not file-system fallback.
### TypeScript/CSS
- Define interfaces for API payloads and component props.
- Avoid broad casts.
- Prefer CSS classes over inline styles except for truly dynamic values.
- For fixed-format UI elements, define stable dimensions with `aspect-ratio`, grid tracks, min/max constraints, or container-relative sizing.
### Verify
```bash
bun run --cwd frontend build
git diff --check -- frontend
rg -n "npm|pnpm|yarn" frontend package.json
```
---
## Module: backend
### Load When
Editing FastAPI, SQLAlchemy, collectors, database models, migrations, services, API routes, or performance-sensitive code.
Also load this module when the user mentions `后端`, `接口`, `API`, `数据库`,
`迁移`, `采集器`, `数据源`, `凭证`, `连通性`, `调度`, `分页`, `性能`,
`慢查询`, `国家/地区`, or files under `backend/`.
### Must
- Use custom exceptions for domain errors.
- Never swallow errors silently.
- Distinguish recoverable and unrecoverable errors.
- Log errors with useful context and appropriate level.
- Propagate errors unless explicitly handled.
- Repeated `load -> validate -> transform -> respond` flow should be centralized.
- Each data source has its own collector class.
- Collectors must inherit the repository's base collector abstraction when available.
- Collectors implement `fetch()` and `transform()` or the current project-equivalent pipeline hooks.
- Support incremental and full sync modes where the source allows it.
### Query Performance
- Never load whole tables into Python for filtering, pagination, counting, dedupe, or summary aggregation.
- Push filters, sorting, pagination, `count`, `distinct`, and grouped statistics down to the database.
- Summary/dashboard endpoints should prefer aggregate queries or aggregate endpoints.
- Avoid selecting large JSON/text payload columns on hot paths unless needed.
- List endpoints default to database-side pagination.
- When a query is slow, first check:
- full-table ORM loads
- Python-side post-filtering
- repeated summary queries that can be merged
- repeated per-request recomputation that should be cached or aggregated
### Country Data
- Data sources carrying country, region, or territory fields must validate against `backend/app/core/countries.py`.
- Use `normalize_country(value)` as the single gate.
- If normalization returns `None`, log and reject or flag the value.
- Do not override canonical political labels with raw source labels.
- Add aliases to `COUNTRY_ENTRIES`; do not scatter aliases across collectors or API handlers.
- Frontend country labels should come from the canonical dictionary after normalization.
### Verify
```bash
git diff --name-only HEAD -- backend
python3 -m py_compile <changed-python-files>
rg -n "scalars\\(\\)\\.all\\(\\)|\\.all\\(\\).*\\[:|len\\(.*\\.all\\(" backend/app
rg -n "text\\(\"SELECT \\*|execute.*SELECT \\*" backend/app
rg -n "normalize_country|COUNTRY_ENTRIES" backend/app
```
---
## Module: earth
### Load When
Editing `frontend/public/earth`, 3D Earth, canvas/Three.js rendering, BGP/vessel/satellite/cable layers, geographic boundaries, or Earth marker icons.
Also load this module when the user mentions `地球`, `三维`, `图层`, `船只`,
`卫星`, `海缆`, `BGP`, `算力中心`, `云图`, `地形`, `marker`, `图标`,
`hover`, `locked`, `tooltip`, `闪烁`, `黑块`, `雪花`, `z-fighting`,
or files under `frontend/public/earth`.
### Must
- Keep rendering state and UI state explicitly synchronized.
- If a layer is hidden, clear or reconcile related hover, lock, tooltip, and selection state.
- Avoid one-off visual patches before checking render order, coordinate ownership, and data lifecycle.
- Use Three.js for 3D elements.
- Verify 3D/canvas work with real rendering, not only TypeScript build.
- For concentric or near-concentric Earth surface shells, do not place overlay radii too close to `CONFIG.earthRadius`.
Maintain explicit altitude offsets with enough separation for far-zoom depth-buffer precision, document them in `earth-render-layer-order.md`, and verify at zoomed-out views such as 50%.
If snow, black blocks, or flicker appears on the globe, check for z-fighting between the base sphere, land/ocean fill, HD texture, terrain, clouds, and occluder before hiding layers or adding LOD workarounds.
- Do not let loading messages, phase labels, or optimistic UI override real backend task state.
- WebSocket data frames should include timestamps, type, and payload when streaming Earth state.
- Default heartbeat for real-time streams is 30 seconds unless a protocol states otherwise.
### Icon System
Canvas-drawn marker icons for Earth must have canonical SVG sources in:
```text
frontend/public/earth/assets/icons/
```
This directory is the single source of truth for icon geometry. Canvas or Three.js drawing code may use `Path2D` strings or draw calls derived from these SVGs, but the shape must originate here.
Naming:
| Prefix | Context |
|--------|---------|
| `marker-` | Surface map markers |
| `bgp-` | BGP/routing layer icons and event symbols |
| `compute-` | Compute center markers |
Rules:
- Use `fill="currentColor"` for single-color icons.
- Hardcode brand colors only when color is part of icon identity.
- State variants are handled by calling code via color/opacity; do not create separate SVGs per state.
- Use the native canvas coordinate space as `viewBox`, typically `0 0 128 128`.
- When adding an icon, create the SVG, document it in this module, and reference its geometry from rendering code.
Current icons:
| File | Used in | Description |
|------|---------|-------------|
| `marker-landing-point.svg` | `cables.js` | Cable landing point pin |
| `bgp-collector.svg` | `bgp.js` | BGP collector marker |
| `bgp-glow-dot.svg` | `bgp.js` | Base radial glow dot |
| `bgp-event-ring.svg` | `bgp.js` | Event ring overlay |
| `bgp-event-triangle.svg` | `bgp.js` | Origin anomaly |
| `bgp-event-exclamation.svg` | `bgp.js` | Withdraw event |
| `bgp-event-wave.svg` | `bgp.js` | Flap event |
| `bgp-event-burst.svg` | `bgp.js` | Specific/burst anomaly |
| `bgp-event-leak.svg` | `bgp.js` | Route leak |
| `bgp-event-dot.svg` | `bgp.js` | Generic event |
| `compute-supercomputer.svg` | `compute-centers.js` | Supercomputer |
| `compute-gpu-cluster.svg` | `compute-centers.js` | GPU cluster |
### Verify
```bash
bun run --cwd frontend build
rg -n "hover|locked|selected|tooltip|visible|Path2D|drawImage" frontend/public/earth
ls frontend/public/earth/assets/icons/
```
---
## Module: ai
### Load When
Editing AI Provider, LLM gateway, AI Playground, prompt templates, model selection, custom collector mapping generation, or LLM-assisted data transformation.
Also load this module when the user mentions `AI Provider`, `模型供应商`,
`Playground`, `提示词`, `prompt`, `mapping`, `自定义采集器`, `base_url`,
`service_token`, `OCR`, `WebSearch`, `Tavily`, or provider credentials.
### Must
- AI provider endpoint/base URL/model/token configuration belongs in settings/integration config, not hardcoded page state.
- The local API route used by the console is not the same as the external LLM provider base URL.
- Common LLM provider presets should be selectable and refreshable from provider docs or catalog logic.
- Store fallback/default provider config centrally.
- Credential previews must reuse the existing product masking convention instead of inventing page-local display logic.
- Never send secrets to logs or docs.
- LLMs may assist with mapping generation or unknown API exploration, but runtime collection should use saved deterministic mapping rules.
- If custom collectors transform into existing domain data, require an explicit target schema.
- If custom collectors introduce entirely new data, do not pretend Earth can use it until a corresponding feature exists.
- Prompts, mapping schemas, default examples, and provider constants must be centralized.
### Verify
```bash
rg -n "AI_PROVIDER|provider_api|base_url|api_key|service_token|prompt|mapping" backend aiprovider frontend/src
git diff --check -- backend aiprovider frontend/src
```
---
## Module: release
### Load When
The user asks to `发版`, bump version, release, commit/push release work, or update changelog/version history as part of a release.
Also load this module when the user mentions `发布`, `打包`, `版本号`,
`CHANGELOG`, `version-history`, tag, release branch, or asks to commit/push a
release-oriented change.
### Must
- Treat release work as release workflow, not a plain commit.
- Use `.codex/skills/release/SKILL.md` when Codex performs a release.
- Version bump rules:
- `feature` -> `+0.1.0`
- `improvement` -> `+0.0.1`
- `bugfix` -> `+0.0.1`
- `docs`, `maintenance`, `refactor` do not bump unless explicitly requested
- Mixed bugfix and small feature/UI work defaults to `improvement` unless the user explicitly chooses another release type.
- A release bump updates all version-bearing files together:
- `VERSION`
- `frontend/package.json`
- `pyproject.toml`
- `uv.lock`
- A release bump updates release records together:
- `docs/CHANGELOG.md`
- `docs/version-history.md`
- `uv.lock` must be regenerated by `uv lock`, never edited manually.
- Before committing a release, verify target version consistency.
- Before pushing a release, run the smallest relevant validation for the changed scope and report what was or was not validated.
- Do not include generated runtime output directories in release commits.
### Verify
```bash
git branch --show-current
git status --short
cat VERSION
rg -n "\"version\":|^version =|version = " frontend/package.json pyproject.toml uv.lock
git diff --stat HEAD
```