diff --git a/.claude/commands/cleanup.md b/.claude/commands/cleanup.md new file mode 100644 index 00000000..68c17323 --- /dev/null +++ b/.claude/commands/cleanup.md @@ -0,0 +1,120 @@ +--- +description: 审查当前工作区未提交代码中的垃圾代码,并在不影响逻辑的前提下自动清理 +argument-hint: 可选:指定要检查的文件或目录(默认检查所有未提交修改) +allowed-tools: ["Read", "Edit", "Bash", "Grep", "Glob"] +--- + +# /cleanup — 垃圾代码审查与清理 + +分析当前工作区(git diff)中的未提交代码,找出并修复常见垃圾代码,**不得改变任何运行逻辑**。 + +## 检查范围 + +若 `$ARGUMENTS` 非空,则只检查指定文件/目录;否则检查所有未提交修改(`git diff HEAD`)。 + +## 审查清单 + +按优先级检查以下问题(只报告在本次 diff 中**新增或修改**的代码里存在的问题): + +### 1. 重复逻辑 (Duplicate Logic) +- 完全相同或高度相似的代码块在多处出现 +- 同一函数/方法被多个地方各自实现,已有公共版本未被复用 +- 相同的 DOM 查询、正则、模板字符串在同一文件重复 + +### 2. Magic Numbers / Magic Strings +- 裸数字直接参与计算(如偏移量、时间、尺寸、阈值),没有命名常量 +- 硬编码字符串(如 id 名、状态值、URL 片段)散落在逻辑中 +- 例外:`0`, `1`, `-1`, `100`, `""` 等语义明确的惯用值不算 + +### 3. 命名问题 +- 含义不明的缩写变量(如 `or_`, `tmp2`, `x2`) +- 命名与实际用途不符 +- 同一概念在不同地方用不同名字表达 + +### 4. 死代码 / 无效代码 +- 注释掉的旧代码块(3行以上) +- 声明后从未使用的变量/参数/导入 +- 永远不会执行的条件分支 + +### 5. 代码风格问题 +- 尾部空白字符(trailing whitespace) +- 同一文件内风格不一致(如混用单双引号、缩进不统一) +- 空行使用不一致(连续多个空行等) + +### 6. 其他常见问题 +- 私有辅助函数应被 export 但没有,导致调用方重复实现 +- 类型/接口重复定义 +- 过于冗长的条件表达式可以简化(不改逻辑) + +## 执行步骤 + +### Step 1 — 获取待检查文件列表 + +```bash +# 无参数时:获取所有未提交修改 +git diff HEAD --name-only + +# 有参数时:用 $ARGUMENTS 过滤 +``` + +### Step 2 — 逐文件阅读并分析 + +- 用 Read 工具读取完整文件(不只读 diff) +- 对照审查清单,记录每个问题:文件名、行号、问题类型、建议修复方式 + +### Step 3 — 报告问题清单 + +在修改前,先以列表形式输出所有发现的问题: + +``` +发现 N 个问题: + +[文件] js/foo.js + · L34, L78: 重复逻辑 — 两处都实现了相同的 DOM 查询,可提取到 getPanel() + · L91: Magic number — 硬编码 14 作为偏移量,应命名为 TOOLTIP_OFFSET + +[文件] js/bar.js + · L12: 命名问题 — 变量 `or_` 语义不明,应命名为 outerR/outerG/outerB + ... +``` + +如果没有发现问题,直接输出"未发现垃圾代码,当前代码质量良好。"并停止。 + +### Step 4 — 执行修复 + +对每个问题,使用 Edit 工具进行**最小化修改**: + +- **重复逻辑**:提取为共享常量/函数,更新所有调用点 +- **Magic number**:在文件顶部或逻辑附近声明 `const NAME = value`,替换所有引用 +- **命名问题**:重命名变量,更新所有使用处 +- **死代码**:直接删除 +- **尾部空白/风格**:修正 +- **未 export 的函数**:添加 `export`,在调用方改为导入(不重复实现) + +**修复原则:** +- 只改在审查清单中发现的问题,不做额外优化 +- 每次 Edit 只修改确实有问题的行,保持 diff 最小 +- 改完后用 `grep` 验证旧的坏代码已消失 + +### Step 5 — 输出总结 + +``` +清理完成: + +修复了 N 个问题: + ✓ earth.js — 提取重复 vertexShader 为 ATMOS_VERTEX_SHADER 常量 + ✓ main.js — 提取 TOOLTIP_CURSOR_OFFSET = 14(4处引用) + ✓ controls.js — export updateLayerButtonState,移除 main.js 中的重复实现 + ... + +未修改的问题(需人工确认): + ! foo.js L45 — 注释代码块较长,建议手动确认是否可删除 +``` + +## 约束 + +- **禁止**改变函数签名、接口定义、导出 API(除非问题正是私有函数应被 export) +- **禁止**添加新功能、新抽象、新参数 +- **禁止**修改注释内容(只删除注释掉的死代码) +- **禁止**修改测试文件逻辑 +- 如果一个 Magic number 的语义不完全确定,**跳过**,在总结中标记为"需人工确认" diff --git a/.claude/commands/release.md b/.claude/commands/release.md new file mode 100644 index 00000000..4065b835 --- /dev/null +++ b/.claude/commands/release.md @@ -0,0 +1,145 @@ +--- +description: 发版工作流:根据变更类型决定版本号,更新所有版本文件和 changelog,运行验证,commit 并 push +argument-hint: 可选:feature | bugfix | 或直接描述本次发布内容 +allowed-tools: ["Read", "Edit", "Bash", "Glob", "Grep"] +--- + +# /release — Planet 发版工作流 + +## 版本号规则 + +| 变更类型 | 版本跳动 | +|---------|---------| +| `feature` | `+0.1.0` | +| `bugfix` | `+0.0.1` | +| `docs` / `maintenance` / `refactor` | 默认不发版,除非用户明确要求 | + +意图混合时以用户明确描述为准。 + +## 必须同步更新的文件 + +使用 `git rev-parse --show-toplevel` 获取仓库根目录,以下路径均相对于根目录: + +- `VERSION` +- `frontend/package.json`(`"version"` 字段) +- `pyproject.toml`(`version =` 字段) +- `uv.lock`(**不要手动编辑**,通过 `uv lock` 重新生成) +- `docs/CHANGELOG.md` +- `docs/version-history.md` + +## 执行步骤 + +### Step 1 — 环境检查 + +```bash +git branch --show-current # 确认在 dev 分支 +git status --short # 检查是否有无关的未暂存修改 +cat VERSION # 读取当前版本 +``` + +若当前**不在 `dev` 分支**,停下来告知用户,不要继续。 + +若存在无关的未暂存修改,列出并询问用户是否一并提交,或先 stash。 + +### Step 2 — 确定发版类型与新版本号 + +- 若 `$ARGUMENTS` 提供了明确类型(`feature` / `bugfix`),直接使用 +- 否则根据当前 `git diff HEAD` 和 `git log` 推断 +- 计算新版本号(例:`0.26.2` → bugfix → `0.26.3`) +- **先输出发版计划供用户确认**: + +``` +发版计划: + 类型:bugfix + 版本:0.26.2 → 0.26.3 + 分支:dev + 将更新:VERSION, frontend/package.json, pyproject.toml, uv.lock, CHANGELOG.md, version-history.md +``` + +### Step 3 — 更新版本号文件 + +按顺序更新(每步用 Edit 工具,精确替换,不要重写整个文件): + +1. `VERSION` — 直接替换全部内容为新版本号 +2. `frontend/package.json` — 替换 `"version": "x.x.x"` 行 +3. `pyproject.toml` — 替换 `version = "x.x.x"` 行 +4. 运行 `uv lock` 重新生成 `uv.lock`(在仓库根目录下执行) + +### Step 4 — 更新 CHANGELOG.md + +在文件顶部插入新条目,格式: + +```markdown +## [x.x.x] — YYYY-MM-DD + +### ✨ Features / 🐛 Fixes / 🔧 Improvements +- ...(只列高信号条目,最多 5 条) +- ... + +--- +``` + +日期使用 `date +%Y-%m-%d` 获取今天的日期。 + +### Step 5 — 更新 docs/version-history.md + +- 更新文件头部的"当前开发版本"字段 +- 在时间线表格顶部插入新行:`| vx.x.x | YYYY-MM-DD | 一句话摘要 |` + +### Step 6 — 验证 + +针对本次变更范围做最小验证: + +- Python 文件有修改:`python3 -m py_compile ` +- Frontend 文件有修改:运行项目标准检查(若无则跳过并说明) +- 版本号一致性检查:用 grep 确认 VERSION、package.json、pyproject.toml 中的版本号完全一致 + +```bash +grep -h "version" VERSION frontend/package.json pyproject.toml +``` + +### Step 7 — 提交前预览 + +展示将要提交的文件列表: + +```bash +git diff --stat HEAD +``` + +再次确认所有必须文件都在变更列表中,**不包含**非预期文件(如调试文件、.env 等)。 + +### Step 8 — Commit & Push(用户确认后) + +```bash +git add VERSION frontend/package.json pyproject.toml uv.lock docs/CHANGELOG.md docs/version-history.md +# 若有代码变更也一并 stage +git add + +git commit -m "release: bump version to x.x.x" +git tag vx.x.x +git push origin dev +git push origin vx.x.x +``` + +commit message 固定格式:`release: bump version to x.x.x` + +### Step 9 — 完成确认 + +输出摘要: + +``` +✓ 版本号已更新:0.26.2 → 0.26.3 +✓ CHANGELOG 已更新 +✓ version-history 已更新 +✓ uv.lock 已重新生成 +✓ 验证通过 +✓ commit: release: bump version to 0.26.3 +✓ tag: v0.26.3 +✓ 已 push 到 origin/dev +``` + +## 注意事项 + +- `uv.lock` 只能通过 `uv lock` 生成,绝不手动编辑 +- 发版 commit 只包含版本文件 + 本次功能代码,不混入无关改动 +- 若环境中 `uv` 不可用,说明原因并跳过 lockfile 更新,提醒用户手动运行 diff --git a/.codex/skills/cleanup/SKILL.md b/.codex/skills/cleanup/SKILL.md new file mode 100644 index 00000000..07359c6c --- /dev/null +++ b/.codex/skills/cleanup/SKILL.md @@ -0,0 +1,124 @@ +--- +name: cleanup +description: Use when the user asks to clean up, lint, or review uncommitted code for common code smells — duplicate logic, magic numbers, unclear naming, dead code, style inconsistencies. Fixes issues without changing any runtime behavior. +--- + +# Cleanup + +Review and fix code quality issues in the current working tree without altering any logic or behavior. + +## When To Use + +- The user asks to clean up, tidy, or lint uncommitted changes +- The user wants a code smell review before releasing or committing +- The user mentions magic numbers, duplicate logic, dead code, or naming issues + +Do not refactor architecture, add features, or change behavior. + +## Scope + +If the user specifies a file or directory, check only that. Otherwise check all uncommitted changes (`git diff HEAD`). + +Only report issues present in **newly added or modified** lines of this diff — do not audit unchanged code. + +## Checklist + +### 1. Duplicate Logic +- Identical or near-identical code blocks appearing in multiple places +- A function/helper that already exists but is re-implemented elsewhere instead of being reused +- Repeated DOM queries, regex literals, or template strings within the same file + +### 2. Magic Numbers / Magic Strings +- Bare numeric literals used in calculations (offsets, timeouts, sizes, thresholds) without a named constant +- Hardcoded strings (IDs, status values, URL fragments) scattered through logic +- Exceptions: `0`, `1`, `-1`, `100`, `""` and other idiomatically clear values are fine + +### 3. Naming Issues +- Cryptic abbreviations (`or_`, `tmp2`, `x2`) +- Names that do not match actual behavior +- The same concept referred to by different names in different places + +### 4. Dead Code +- Commented-out code blocks (3+ lines) +- Variables, parameters, or imports declared but never used +- Branches that can never execute + +### 5. Style Inconsistencies +- Trailing whitespace +- Mixed quote styles or indentation within the same file +- Inconsistent blank-line usage (multiple consecutive blank lines, etc.) + +### 6. Other +- Private helper functions that should be exported but are not, causing callers to duplicate the implementation +- Overly verbose conditions that can be simplified without changing logic + +## Steps + +### Step 1 — Get the file list + +```bash +git diff HEAD --name-only +``` + +Filter to the user-specified path if one was provided. + +### Step 2 — Read and analyze each file + +Read the full file (not just the diff) with the Read tool. For each file, record every issue found: filename, line number, category, and suggested fix. + +### Step 3 — Report findings before touching anything + +Print a structured list: + +``` +Found N issues: + +[file] js/foo.js + · L34, L78: Duplicate logic — same DOM query implemented twice; extract to getPanel() + · L91: Magic number — bare 14 used as pixel offset; name it TOOLTIP_OFFSET + +[file] js/bar.js + · L12: Naming — variable `or_` is unclear; rename to outerR, outerG, outerB + ... +``` + +If no issues are found, output "No code smells detected. Code quality looks good." and stop. + +### Step 4 — Fix each issue + +Use the Edit tool for **minimal, targeted changes**: + +- **Duplicate logic**: extract to a shared constant or function; update all call sites +- **Magic number/string**: declare `const NAME = value` near the top of the relevant scope; replace all usages +- **Naming**: rename the variable/function; update all references +- **Dead code**: delete it +- **Trailing whitespace / style**: fix in place +- **Unexported helper**: add `export`; update callers to import instead of re-implementing + +Principles: +- Only fix issues identified in the checklist — no extra improvements +- Keep each Edit as small as possible +- After fixing, verify the old bad pattern is gone with grep + +### Step 5 — Summary + +``` +Cleanup complete: + +Fixed N issues: + ✓ earth.js — extracted duplicate vertexShader into ATMOS_VERTEX_SHADER constant + ✓ main.js — extracted TOOLTIP_CURSOR_OFFSET = 14 (4 references updated) + ✓ controls.js — exported updateLayerButtonState; removed duplicate implementation in main.js + ... + +Skipped (needs manual review): + ! foo.js L45 — large commented-out block; confirm it is safe to delete +``` + +## Constraints + +- **Do not** change function signatures, exported interfaces, or public APIs (unless the issue is a missing export) +- **Do not** add new features, abstractions, or parameters +- **Do not** rewrite comments (only delete commented-out dead code) +- **Do not** touch test file logic +- If a magic number's intent is uncertain, skip it and flag it in the summary diff --git a/.codex/skills/release-workflow/SKILL.md b/.codex/skills/release-workflow/SKILL.md deleted file mode 100644 index 512f6169..00000000 --- a/.codex/skills/release-workflow/SKILL.md +++ /dev/null @@ -1,78 +0,0 @@ ---- -name: release-workflow -description: Use when the user asks to release, bump version, update changelog/version files, or commit/push a repository release for the Planet repo. Applies the repo's versioning rules, updates all required version-bearing files, updates changelog/version-history, runs minimal relevant validation, and then commits/pushes when requested. ---- - -# Release Workflow - -Use this skill for release-oriented work in this repository. - -## When To Use - -- The user asks to `发版` -- The user asks to bump a version -- The user asks to update `CHANGELOG`, `version-history`, or version files as part of a release -- The user asks to commit/push a release or a publishable bugfix/feature bundle - -Do not use this skill for ordinary commits that are not being released. - -## Versioning Rules - -- `feature` -> bump `+0.1.0` -- `bugfix` -> bump `+0.0.1` -- `docs`, `maintenance`, and `refactor` do not bump by default unless the user explicitly wants a release - -When intent is mixed, prefer the user’s stated release intent. If they ask to release a bugfix bundle, use a patch bump. - -## Required Files - -Every release bump must update these files together: - -- `/home/ray/dev/linkong/planet/VERSION` -- `/home/ray/dev/linkong/planet/frontend/package.json` -- `/home/ray/dev/linkong/planet/pyproject.toml` -- `/home/ray/dev/linkong/planet/uv.lock` -- `/home/ray/dev/linkong/planet/docs/CHANGELOG.md` -- `/home/ray/dev/linkong/planet/docs/version-history.md` - -## Workflow - -1. Inspect the current worktree and current version. -2. Decide the release type from the user request: - - feature - - bugfix - - release without code changes -3. Compute the next version. -4. Update all required version-bearing files. -5. Add a concise but specific changelog entry: - - highlights - - important added/improved/fixed items - - mention the highest-signal files only -6. Update `docs/version-history.md`: - - current dev version - - new timeline row with summary -7. Run the smallest relevant validation available. -8. Before commit, verify the target version is present in all required files. -9. If the user asked for commit/push: - - stage the release files and code changes - - commit with a conventional message - - push to the requested branch, usually `dev` - -## Validation Guidance - -- Prefer scope-matched validation over broad expensive checks -- Typical examples: - - Python backend edits: `python3 -m py_compile ...` - - Frontend edits: use the project-standard frontend build/check if available -- If the environment prevents a check, say that explicitly in the final summary - -## Release Checklist - -Before closing the task, confirm: - -- version bump applied consistently -- changelog updated -- version history updated -- generated/runtime artifacts are not accidentally staged -- validation status recorded -- commit and push completed if requested diff --git a/.codex/skills/release/SKILL.md b/.codex/skills/release/SKILL.md new file mode 100644 index 00000000..cd02b3fd --- /dev/null +++ b/.codex/skills/release/SKILL.md @@ -0,0 +1,157 @@ +--- +name: release +description: Use when the user asks to release, bump version, update changelog/version files, or commit/push a repository release for the Planet repo. Determines version bump type from changes, updates all required version-bearing files, updates changelog and version-history, runs minimal validation, then commits, tags, and pushes. +--- + +# Release Workflow + +Use this skill for release-oriented work in this repository. + +## When To Use + +- The user asks to `发版` +- The user asks to bump a version +- The user asks to update `CHANGELOG`, `version-history`, or version files as part of a release +- The user asks to commit/push a release or a publishable bugfix/feature bundle + +Do not use this skill for ordinary commits that are not being released. + +## Versioning Rules + +- `feature` -> bump `+0.1.0` +- `bugfix` -> bump `+0.0.1` +- `docs`, `maintenance`, and `refactor` do not bump by default unless the user explicitly wants a release + +When intent is mixed, prefer the user's stated release intent. + +## Required Files + +Use `git rev-parse --show-toplevel` to get the repo root. All paths are relative to it: + +- `VERSION` +- `frontend/package.json` (`"version"` field) +- `pyproject.toml` (`version =` field) +- `uv.lock` (**never edit manually** — regenerate by running `uv lock`) +- `docs/CHANGELOG.md` +- `docs/version-history.md` + +## Workflow + +### Step 1 — Environment check + +```bash +git branch --show-current # must be on dev +git status --short # check for unrelated uncommitted changes +cat VERSION # read current version +``` + +If not on `dev`, stop and tell the user. Do not proceed. + +If unrelated uncommitted changes exist, list them and ask the user whether to include them or stash first. + +### Step 2 — Determine release type and next version + +- If the user provided an explicit type (`feature` / `bugfix`), use it +- Otherwise infer from `git diff HEAD` and recent `git log` +- Compute the next version (e.g. `0.26.2` → bugfix → `0.26.3`) +- **Show the release plan before making any changes:** + +``` +Release plan: + Type: bugfix + Version: 0.26.2 → 0.26.3 + Branch: dev + Will update: VERSION, frontend/package.json, pyproject.toml, uv.lock, CHANGELOG.md, version-history.md +``` + +### Step 3 — Update version files + +Update in order (use Edit for precise replacement, never rewrite whole files): + +1. `VERSION` — replace entire content with new version string +2. `frontend/package.json` — replace `"version": "x.x.x"` line +3. `pyproject.toml` — replace `version = "x.x.x"` line +4. Run `uv lock` at repo root to regenerate `uv.lock` + +### Step 4 — Update CHANGELOG.md + +Insert a new entry at the top of the file: + +```markdown +## x.x.x + +Released: YYYY-MM-DD + +### Highlights + +- ... + +### Added / Fixed / Improved + +- ... (high-signal items only, max 5) + +--- +``` + +Get today's date with `date +%Y-%m-%d`. + +### Step 5 — Update docs/version-history.md + +- Update the "current dev version" field in the file header +- Insert a new row at the top of the timeline table: `| vx.x.x | YYYY-MM-DD | one-line summary |` + +### Step 6 — Validate + +Run the smallest relevant validation for the changes in scope: + +- Python files changed: `python3 -m py_compile ` +- Frontend files changed: run the project-standard check if available; otherwise skip and say so +- Version consistency: confirm VERSION, package.json, pyproject.toml, and uv.lock all show the same version + +```bash +grep -h "version" VERSION frontend/package.json pyproject.toml +``` + +### Step 7 — Pre-commit preview + +Show what will be committed: + +```bash +git diff --stat HEAD +``` + +Confirm all required files are present and no unexpected files (debug files, `.env`, etc.) are included. + +### Step 8 — Commit, tag, and push + +```bash +git add VERSION frontend/package.json pyproject.toml uv.lock docs/CHANGELOG.md docs/version-history.md +# also stage any code changes included in this release +git add + +git commit -m "release: bump version to x.x.x" +git tag vx.x.x +git push origin dev +git push origin vx.x.x +``` + +Commit message format is fixed: `release: bump version to x.x.x` + +### Step 9 — Completion summary + +``` +✓ Version bumped: 0.26.2 → 0.26.3 +✓ CHANGELOG updated +✓ version-history updated +✓ uv.lock regenerated +✓ Validation passed +✓ commit: release: bump version to 0.26.3 +✓ tag: v0.26.3 +✓ Pushed to origin/dev +``` + +## Notes + +- `uv.lock` must only be updated by running `uv lock`, never manually +- The release commit should include only version files + the code for this release — no unrelated changes +- If `uv` is unavailable in the environment, say so explicitly and remind the user to run it manually