Files
planet/rules.md
rayd1o 83a10a6c34
Some checks failed
release / images (push) Waiting to run
ci / backend (push) Has been cancelled
ci / frontend (push) Has been cancelled
ci / delivery (push) Has been cancelled
release: bump version to 0.74.6
2026-09-16 21:05:40 +08:00

25 KiB

name, description
name description
planet-rules 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:

# 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:

// 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:
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

git diff --name-only HEAD
rg -n "api[_-]?key|client_secret|BEGIN .*PRIVATE KEY|AKIA[0-9A-Z]" .

Module: workflow

Load When

Always.

Harness

  • rules.md is the active repository rule source. Keep durable constraints here instead of duplicating them across prompt files.
  • Use .codex/skills/ for specialized Codex workflows such as cleanup, docs, goal-driven work, and release.
  • Do not add new legacy harness entry points when an existing skill or rule module can carry the same instruction.
  • Keep confirmed operational failure causes in the error catalog in docs/technical/{zh,en}/ops-runbook.md. planet.sh diagnostics must read causes and remedies from this catalog. Add a stable error code, matching evidence, and a regression case when fixing a previously unclassified cause; unknown failures must remain explicitly unclassified until verified.
  • If a harness rule is no longer true for the current toolchain, update or delete it in the same cleanup pass.

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.

Visual Evidence Gate

  • If the user provides a screenshot, image, video frame, visual mock, browser capture, or says something like "as shown", obtain evidence from that artifact before interpreting the request or changing code.
  • Path resolution is part of the task. If a provided path does not open, try reasonable local equivalents first, such as WSL/Windows path conversion, workspace-relative paths, absolute paths, and attached-file locations.
  • If the artifact still cannot be found or opened, stop that visual-dependent work and report the exact path/access problem instead of guessing. Ask for an accessible file/path or a fresh screenshot.
  • Do not infer visual intent from the filename, surrounding text, alt text, logs, or prior assumptions.
  • OCR is acceptable evidence for text-only questions or when the active environment lacks multimodal image viewing, but state that OCR was the fallback. Layout, color, spacing, pixel, and rendering issues still require a real visual inspection or an explicit "could not verify visually" note.
  • After inspecting the artifact, ground the work in at least one concrete observed detail when it affects the task.
  • For UI or rendering fixes that depend on appearance, verify with a real screenshot or browser render when the project can be run locally.

Deterministic Context

  • Prefer compact CLI evidence over reading large files or full diffs:
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

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:

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

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:
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

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

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:

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

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

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

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