Files
planet/rules.md
2026-05-12 17:15:02 +08:00

18 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.


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.

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

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.

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.

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.

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.

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.
  • 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.

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.

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