docs: formalize release workflow and frontend layout guardrails

This commit is contained in:
rayd1o
2026-04-10 03:08:39 +08:00
parent 749e6e76b6
commit fbb6adfbf5
9 changed files with 284 additions and 22 deletions

View File

@@ -0,0 +1,78 @@
---
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 users 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

View File

@@ -1 +1 @@
0.24.6
0.24.7

View File

@@ -7,34 +7,22 @@ This project follows the repository versioning rule:
- `feature` -> `+0.1.0`
- `bugfix` -> `+0.0.1`
## 0.24.5
## 0.24.7
Released: 2026-04-10
### Highlights
- Turned the first BGP AI brief flow into a persistent operator-facing feature with saved Markdown history, tabbed review, and backend-driven fact assembly, while also cutting BGP page load cost by switching the hottest routes away from Python-side full-table scans.
- Formalized repository release hygiene and frontend layout guardrails so repeated versioning chores and recurring layout regressions now have explicit repo-level rules instead of living only in conversation context.
### Added
- Added [backend/app/services/bgp_ai_brief.py](/home/ray/dev/linkong/planet/backend/app/services/bgp_ai_brief.py), building evidence-first BGP brief prompts from incidents, anomalies, observations, and collector coverage instead of relying on manual Playground inputs.
- Added [backend/app/services/bgp_ai_brief_store.py](/home/ray/dev/linkong/planet/backend/app/services/bgp_ai_brief_store.py), persisting generated BGP AI briefs as Markdown files and exposing a stable record shape for history browsing.
- Added [frontend/src/components/MarkdownRenderer/MarkdownRenderer.tsx](/home/ray/dev/linkong/planet/frontend/src/components/MarkdownRenderer/MarkdownRenderer.tsx), giving the frontend a lightweight built-in Markdown renderer for saved AI brief content without introducing a new dependency.
- Added [backend/app/api/v1/bgp.py](/home/ray/dev/linkong/planet/backend/app/api/v1/bgp.py) `GET /bgp/overview/summary`, consolidating the BGP overview summary hot path into a dedicated aggregate endpoint for the BGP workspace.
- Added [release-workflow/SKILL.md](/home/ray/dev/linkong/planet/.codex/skills/release-workflow/SKILL.md), defining the repository release workflow for version bumps, changelog/version-history updates, minimal validation, and commit/push sequencing.
### Improved
- Improved [backend/app/api/v1/ai.py](/home/ray/dev/linkong/planet/backend/app/api/v1/ai.py) and [backend/app/schemas/ai.py](/home/ray/dev/linkong/planet/backend/app/schemas/ai.py) by extending the AI API from one-off analysis calls to saved BGP brief history endpoints, latest-brief lookup, and persisted brief responses.
- Improved [frontend/src/pages/BGP/BGP.tsx](/home/ray/dev/linkong/planet/frontend/src/pages/BGP/BGP.tsx) by moving `AI 简报` into the trailing tab, loading tab data lazily, loading brief history only on demand, and wiring saved brief selection plus regeneration into the operator workflow.
- Improved [frontend/src/services/situational-awareness/http-gateway.ts](/home/ray/dev/linkong/planet/frontend/src/services/situational-awareness/http-gateway.ts), [frontend/src/services/situational-awareness/port.ts](/home/ray/dev/linkong/planet/frontend/src/services/situational-awareness/port.ts), [frontend/src/services/situational-awareness/mock-gateway.ts](/home/ray/dev/linkong/planet/frontend/src/services/situational-awareness/mock-gateway.ts), and [frontend/src/services/situational-awareness/types.ts](/home/ray/dev/linkong/planet/frontend/src/services/situational-awareness/types.ts) by splitting BGP summary, list, and brief-history fetches into more granular gateway methods and de-duplicating in-flight requests on the hot path.
- Improved [frontend/src/index.css](/home/ray/dev/linkong/planet/frontend/src/index.css) by styling the saved BGP brief workspace, Markdown output, history selector, and responsive compact state without re-breaking tab switching.
- Improved [backend/app/services/bgp_collectors.py](/home/ray/dev/linkong/planet/backend/app/services/bgp_collectors.py) by replacing full-table ORM loading with database-side collector aggregation, latest-record lookup, and top-event summarization for the collector coverage hot path.
### Fixed
- Fixed the BGP tab rendering regression in [frontend/src/index.css](/home/ray/dev/linkong/planet/frontend/src/index.css) where forcing tab panes to `display: flex` accidentally kept hidden panes visible and made the first tab look permanently locked.
- Fixed [backend/app/api/v1/bgp.py](/home/ray/dev/linkong/planet/backend/app/api/v1/bgp.py) so `events`, `anomalies`, and `incidents` no longer fetch whole tables into Python just to apply filtering, pagination, and counting.
- Fixed the repository workflow around saved BGP brief artifacts by ignoring [data/ai/bgp-briefs/](/home/ray/dev/linkong/planet/data/ai/bgp-briefs/) in [.gitignore](/home/ray/dev/linkong/planet/.gitignore) instead of leaving runtime Markdown output to pollute git status during normal operator use.
- Improved [rules.md](/home/ray/dev/linkong/planet/rules.md) by adding mandatory release-workflow requirements and a new frontend layout constraint section covering single-screen workspaces, overflow ownership, tab-pane behavior, compact-mode expectations, and readable-card fallbacks.
- Improved [frontend-layout-guidelines.md](/home/ray/dev/linkong/planet/docs/frontend-layout-guidelines.md) by summarizing the recurring Earth, Playground, BGP, and admin-layout regressions into concrete constraints for future frontend work, including “prefer scrollbars over unreadable compression” and “do not treat every tab as a table pane.”
## 0.24.6

View File

@@ -82,6 +82,145 @@
- 工作区容器通常需要 `display: flex`
- 真正的滚动节点要显式 `overflow: auto`
### 6. 卡片不能被压到不可读
历史上我们反复踩到的问题不是“没有滚动条”,而是:
- 卡片被 `flex` 压缩得只剩一小条可视区域
- 文字能渲染,但读不完整
- 内容其实存在,却被 `overflow: hidden` 裁掉
因此后续约束是:
- 先保证卡片有可读的最小高度
- 如果继续压缩会影响阅读,就切换成内部滚动
- 不要为了“保持一屏”而把正文、表格、描述区压成无法阅读的条状区域
### 7. Tabs 不是天然安全的布局容器
历史上 Tabs 相关回归非常多,典型问题包括:
- 隐藏 tab pane 因为自定义 `display: flex` 而重新露出来
- 所有 tab 被强行套用同一套高度/overflow 规则
- 表格 tab 能工作,但 markdown / help / diagnostics tab 被压坏
因此约束是:
- `Tabs` 里的每类内容都要单独定义自己的布局策略
- 表格 tab 可以是“固定高度 + 内部滚动”
- 文档/Markdown tab 更适合“tab pane 自身滚动 + 内容正常文档流”
- 如果覆盖组件库样式,必须同时检查 hidden 状态是否仍然成立
### 8. 摘要区优先进入紧凑模式,而不是挤压正文
历史经验表明,最容易被误处理的是顶部摘要卡:
- 它们经常为了“都放下”被强行压窄
- 然后正文、表格、AI 结果区一起失去主空间
后续统一约束:
- 小屏或高缩放时,摘要卡优先:
- 降低 padding
- 改成横向滚动
- 改成更紧凑的网格
- 不要优先牺牲主工作区的可视面积
### 9. 长文档类内容优先保证阅读体验
像下面这些内容,不能直接套用“表格工作区”的逻辑:
- AI 简报
- 运行日志
- 原始 JSON
- 帮助说明
- 多段描述性文本
这些区域应该优先满足:
- 标题和元信息稳定可见
- 正文有明确的最小可读高度
- 正文滚动策略单独定义
- 支持 Markdown 表格、分隔线、引用、代码块等结构
### 10. 高度关键路径要少包一层
历史上不少滚动问题不是组件本身错,而是多包了一层之后:
- 高度链路断掉
- `min-height: 0` 没传下去
- `overflow` 责任被吃掉
因此:
- 对高度关键区域,优先使用最直接的 DOM 结构
- 使用 `Space`、额外包装 `div`、第三方布局容器时,要确认它们不会改变滚动和高度语义
- 如果一个区域已经出现“内容明明有,但只剩一条缝”,优先怀疑中间包装层
## 历史坑位总结
从 Earth、Playground、BGP、DataSources 这些页面的 bugfix 可以归纳出几类高频坑:
### 1. 用 `overflow: hidden` 掩盖布局问题
表面上看页面“整齐了”,实际上会导致:
- 内容被裁掉
- tab 内容只剩一条缝
- 面板明明渲染成功,但用户看不见
正确做法:
- 让真正的内容节点滚动
- 不要让上层容器无差别裁剪所有子内容
### 2. 把所有 tab 当成同一种内容
表格、Markdown、帮助卡、日志流的空间需求完全不同。
正确做法:
- 表格:固定工作区 + 内部滚动
- 文档:普通流式内容 + pane 级滚动
- 侧边说明:内容驱动高度,不强行拉满
### 3. 只做视觉缩小,不做空间重分配
这会导致:
- 卡片文字被截断
- 表格只剩 1 到 2 行
- 按钮和筛选区挤成一团
正确做法:
- 紧凑模式优先重排
- 横向滚动摘要区
- 折叠/收纳次级模块
### 4. 父容器高度链不完整
这是最常见的内部滚动失效原因。
检查顺序:
1. 外层是否真的有确定高度
2. flex 父容器是否带了 `min-height: 0`
3. 真正滚动节点是否明确 `overflow: auto`
4. 中间包装层是否偷偷改了布局语义
### 5. UI 状态和显示状态不同步
Earth 相关改动里反复出现:
- 图层隐藏了,但 hover/lock 还在
- tooltip 还在显示旧对象
- legend 没跟着切换
这类约束同样适用于后台页面:
- 被隐藏、卸载、切换出视图的内容,不应继续保留活跃交互状态
## 推荐实现模式
### 页面骨架
@@ -149,9 +288,11 @@
- 页头、摘要区、主工作区能否同时出现
- 主工作区是否拿到了页面中最多的高度
- 表格或明细溢出时,滚动条是否出现在模块内部
- 卡片是否被压缩到文字显示不完整;如果会,是否已经切换为内部滚动
- 浏览器缩放到 `125%` / `150%` 时是否仍可用
- 低高度窗口下是否还保有合理的可见内容行数
- Tabs、Card、Table 在 overflow 时是否仍可操作
- 非表格 tabMarkdown、帮助说明、日志是否有独立且合理的滚动策略
## 落地顺序

View File

@@ -16,7 +16,7 @@
## Current Version
- `main` 当前主线历史推导到:`0.16.5`
- `dev` 当前开发分支历史推导到:`0.24.6`
- `dev` 当前开发分支历史推导到:`0.24.7`
## Timeline
@@ -79,6 +79,7 @@
| `0.24.4` | bugfix | `dev` | `pending` | polish `planet.sh` AI Provider rebuild stage boundaries, hide raw Compose build logs on success, and add explicit image-build completion feedback |
| `0.24.5` | bugfix | `dev` | `pending` | add persistent BGP AI briefs with Markdown history, lazy-load BGP tabs, and move BGP hot-path filtering and aggregation back into the database |
| `0.24.6` | bugfix | `dev` | `pending` | batch datasource and visualization hot-path queries, fix BGP collector JSON extraction, and rebuild the BGP AI brief tab layout and markdown rendering |
| `0.24.7` | bugfix | `dev` | `pending` | formalize release workflow and frontend layout constraints with repo rules and a reusable release skill |
## Maintenance Commits Not Counted as Version Bumps

View File

@@ -1,6 +1,6 @@
{
"name": "planet-frontend",
"version": "0.24.6",
"version": "0.24.7",
"private": true,
"packageManager": "bun@1",
"dependencies": {

View File

@@ -1,6 +1,6 @@
[project]
name = "planet"
version = "0.24.6"
version = "0.24.7"
description = "智能星球计划 - 态势感知系统"
requires-python = ">=3.14"
dependencies = [

View File

@@ -239,3 +239,57 @@ class BaseCollector:
- Python-side post-filtering
- repeated summary queries that can be merged
- repeated per-request recomputation that should be cached or aggregated once
---
## Release Workflow - MANDATORY
- When the user asks to `发版`, `bump version`, `release`, or `推送发布类改动`, treat it as a release workflow, not a plain commit
- Apply repository versioning rules consistently:
- `feature` -> `+0.1.0`
- `bugfix` -> `+0.0.1`
- `docs / maintenance / refactor` do **NOT** bump version unless the user explicitly wants a release anyway
- A release bump **MUST** update all version-bearing files together:
- `VERSION`
- `frontend/package.json`
- `pyproject.toml`
- `uv.lock`
- A release bump **MUST** update release records together:
- `docs/CHANGELOG.md`
- `docs/version-history.md`
- Before committing a release, verify the target version appears consistently in all required files
- Before pushing a release, run the smallest relevant validation available for the changed scope and report what was or was not validated
- If runtime output directories are part of the feature flow, confirm they are ignored appropriately so release commits do not accidentally include generated artifacts
- If asked to commit/push release work, do **NOT** skip changelog or version-history updates just because the code changes are small
- Use the repo skill at `/home/ray/dev/linkong/planet/.codex/skills/release-workflow/SKILL.md` whenever performing a release workflow for this repository
---
## Frontend Layout - MANDATORY
- Backend/admin pages must be designed as a `single-screen workspace` first, not as a long vertically stacked document
- In common desktop viewports, users should be able to see:
- page header
- summary/controls
- the main work area
- The main work area must get the majority of the available height; secondary cards must not crowd it out
- If a card or panel would be compressed until text, controls, or tables become unreadable, stop shrinking it and give that region an internal scrollbar instead
- On small screens, high browser zoom, or reduced viewport height, switch to a compact mode or horizontal summary scrolling before allowing important content to be crushed
- Overflow ownership must be explicit:
- parent height chain must be valid
- height-constrained flex parents need `min-height: 0`
- only the intended scroll node should own `overflow: auto`
- Do **NOT** rely on `overflow: hidden` as the final fix for a crowded layout unless another child container is explicitly responsible for scrolling
- For tabs:
- hidden tab panes must stay hidden
- do not override library hidden-pane selectors in a way that makes inactive content visible
- each tab must define its own scroll strategy instead of inheriting a one-size-fits-all table layout
- For long-form content such as AI briefs, logs, markdown, raw JSON, or help text:
- prefer normal document flow inside the content block
- if height is constrained, use a stable minimum readable height plus scrolling
- do not let flex compression collapse the readable area into a thin strip
- Avoid brittle viewport sizing:
- prefer `height: 100%` chains over naive `100vh/100vw` usage in embedded/admin shells
- verify layouts under browser zoom `125%` and `150%`
- Avoid using wrapper components with implicit layout behavior, such as `Space`, for height-critical scroll regions unless their generated DOM is fully accounted for
- Any UI state that hides data or a layer must also reconcile related hover/lock/tooltip/selection state so hidden content is not still “active” in the UI

2
uv.lock generated
View File

@@ -475,7 +475,7 @@ wheels = [
[[package]]
name = "planet"
version = "0.24.6"
version = "0.24.7"
source = { virtual = "." }
dependencies = [
{ name = "aiofiles" },