From 461975bfb2a47aaea4df0649c16767da7828a347 Mon Sep 17 00:00:00 2001 From: kuddev Date: Sun, 6 Sep 2026 16:54:47 +0800 Subject: [PATCH] docs: align Pebrel identity and contribution guidance Use the public project name consistently while retaining compatibility identifiers and existing download names. Publish the contribution, architecture and translation contracts with their enforcement limits. Synchronize the bilingual unreleased changelog and release notes. --- .github/CODEOWNERS | 1 + .github/PULL_REQUEST_TEMPLATE.md | 28 +++++ .gitignore | 39 +++++++ AGENTS.md | 9 ++ CHANGELOG.md | 4 + CONTRIBUTING.md | 127 ++++++++++++++++++++++ INSTALL.md | 6 +- README.md | 92 ++++++++-------- docs/architecture-decisions.md | 60 +++++++++++ docs/architecture.md | 99 +++++++++++++++++ docs/engineering-evidence.md | 53 +++++++++ docs/internationalization.md | 112 +++++++++++++++++++ docs/project-constraints.md | 150 ++++++++++++++++++++++++++ docs/release-notes/unreleased.md | 4 + scripts/tests/test_pebrel_branding.py | 11 +- 15 files changed, 743 insertions(+), 52 deletions(-) create mode 100644 .github/CODEOWNERS create mode 100644 .github/PULL_REQUEST_TEMPLATE.md create mode 100644 CONTRIBUTING.md create mode 100644 docs/architecture-decisions.md create mode 100644 docs/architecture.md create mode 100644 docs/engineering-evidence.md create mode 100644 docs/internationalization.md create mode 100644 docs/project-constraints.md diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..d54473d --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +* @Kuddev diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..b9394e7 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,28 @@ +## Result / 用户结果 + +What changes for users? Link the relevant issue; do not claim unfinished work. + +## Design / 设计边界 + +- Responsibility and affected modules: +- Why this belongs here; interfaces that remain unchanged: +- Dependency, data-format, threading, or lifetime changes (ADR if applicable): +- Compatibility and migration/fallback behavior: + +## Evidence / 验证依据 + +- Commands and actual results (include unrun checks): +- Regression tests: what fails before the fix? +- UI changes: screenshots, long translations, keyboard access, DPI checks: +- Hot-path changes: allocation/work/load measurements, where applicable: + +## Required Review / 必须确认 + +- [ ] I followed `CONTRIBUTING.md`, `docs/architecture.md`, and `docs/project-constraints.md`. +- [ ] I split responsibilities, not arbitrary line ranges; no duplicate behavior authority was added. +- [ ] `python3 scripts/check_architecture.py --base ` passes; budgets were not inflated to fit the change. +- [ ] Tests cover success and failure; platform/feature coverage limitations are stated. +- [ ] New messages use typed i18n IDs and matching placeholders; untranslated content has an explicit fallback. +- [ ] Governance changes include a counterexample, corrected contract, tests, and a maintainer-reviewed decision. + +Checkboxes explain the review; they do not replace CI or maintainer approval. diff --git a/.gitignore b/.gitignore index 16e73df..21a3c1e 100644 --- a/.gitignore +++ b/.gitignore @@ -44,6 +44,12 @@ tocodex-docs/ !/docs/runtime-control-api.md !/docs/runtime-api-v1.schema.json !/docs/preview-release-checklist.md +# Reviewed public engineering guides, not private product/competitor investigations. +!/docs/project-constraints.md +!/docs/architecture.md +!/docs/architecture-decisions.md +!/docs/engineering-evidence.md +!/docs/internationalization.md !/docs/skills/ !/docs/skills/nebula-runtime/ !/docs/skills/nebula-runtime/SKILL.md @@ -57,11 +63,44 @@ tocodex-docs/ # research filenames stay unpublished. docs/**/*-gap-analysis.md docs/**/*-study.md +docs/**/*-research.md +docs/**/*-competitor-*.md +docs/**/research/ +docs/**/reference-projects/ +docs/**/external-probes/ # Local interactive demos belong under the private docs tree. /*.html +/*.htm +/docs/**/*.html +/docs/**/*.htm +*-prototype.html +*_prototype.html +*-mockup.html +*_mockup.html +*-prototype.htm +*_prototype.htm +*-mockup.htm +*_mockup.htm +/prototypes/ /TASKS.md +# Reserved local-only work areas; maintained tests and third_party/ stay visible. +/research/ +/reference-projects/ +/external-probes/ +/scratch/ +/tmp-* +/tmp_* + +# Python-generated caches are not test sources or contract fixtures. +__pycache__/ +*.pyc +*.pyo +.pytest_cache/ +.mypy_cache/ +.ruff_cache/ + # Secrets / credentials / environment — must never be committed .env .env.* diff --git a/AGENTS.md b/AGENTS.md index 93d5145..653ed2e 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,5 +1,14 @@ # Nebula 项目代理指引 +## 强制工程规范 + +- 修改前阅读 `CONTRIBUTING.md`、`docs/architecture.md` 和 `docs/project-constraints.md`;新 UI 文案同时遵循 `docs/internationalization.md`。 +- 行数预算与依赖方向由 `architecture/` 声明,使用 `python3 scripts/check_architecture.py --base ` 验证;800 行仅提示,2000 行是既有防灾上限。 +- 禁止靠抬高预算、删测试、压缩格式、机械分片或静默排除目录让门禁通过。规范存在缺陷时,先给可复现反例,补正反测试并记录经维护者审查的规则修订。 +- 核心规则保持单一权威实现;按职责和生命周期拆分,不因文件夹名称或历史模块别名推断耦合。新增长期依赖、跨层接口、持久化和线程模型变更须给出设计依据。 +- 普通翻译查询维持已测零分配合同;参数格式化和冷路径另行评估。不能把单机微基准写成普遍性能保证。 +- 不得声称仅加入 workflow 或 `CODEOWNERS` 就已启用 GitHub 强制保护;服务端设置及负例 PR 验证须另行获准并核验。 + ## 发布任务的持久化上下文 - 处理版本号、构建、打包、自动更新、GitHub Release、Changelog 或 Release Note 前,必须先完整阅读 [`.agents/memory.md`](.agents/memory.md) 的发布章节。 diff --git a/CHANGELOG.md b/CHANGELOG.md index d4eeed6..2f1630c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,8 @@ Every release entry is provided in English and Simplified Chinese. - File-name indexing applies incremental updates and recovers from watcher queue overflow with a rescan; editing a file's contents alone no longer rebuilds its name entry. - Improved terminal formula parsing and rendering for streamed agent output, while preserving the original text when a formula cannot be rendered. - Added native platform adapters and preview packaging instructions for Linux and macOS. Native build, test and package validation remains a separate requirement before publishing those previews. +- Updated the public project and installation guides to use Pebrel consistently, while retaining the existing repository, command, configuration, and download identifiers. +- Added contribution, architecture, and translation guides with explicit compatibility and review requirements. GitHub branch protection still requires separate server-side setup and verification. ### 简体中文 @@ -49,6 +51,8 @@ Every release entry is provided in English and Simplified Chinese. - 文件名索引采用增量更新,监听队列溢出时通过重新扫描恢复;仅编辑文件内容不再重建对应名称条目。 - 改进流式 Agent 输出中的终端公式解析与绘制,无法渲染时保留原始文本。 - 新增 Linux 和 macOS 原生平台适配及预览打包说明;发布这些预览前仍需单独完成原生构建、测试和打包验证。 +- 公开项目说明与安装指南统一采用 Pebrel 名称,同时保留现有仓库、命令、配置与下载标识。 +- 新增贡献、架构和翻译指南,明确兼容性与审查要求;GitHub 分支保护仍需单独在服务端配置并核验。 ### Contributors - [@Sakyvo](https://github.com/Sakyvo): terminal network proxy, conditional `Ctrl+C` copy, and word deletion with `Ctrl+Backspace` / 终端网络代理、`Ctrl+C` 按选区复制及 `Ctrl+Backspace` 按词删除。 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..e285a0f --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,127 @@ +# Contributing to Pebrel / 贡献指南 + +Pebrel is the project name. The repository remains `Kuddev/nebula`; existing +`nebula` CLI, configuration, installation and update identifiers are compatibility +interfaces, not opportunities for search-and-replace renaming. + +## Required reading + +- [Architecture and module ownership](docs/architecture.md) +- [Enforced contracts and review rules](docs/project-constraints.md) +- [Decision log and policy change process](docs/architecture-decisions.md) +- [Evidence behind the rules](docs/engineering-evidence.md) +- [Internationalization](docs/internationalization.md) when changing UI text + +These rules apply equally to maintainers, outside contributors and coding agents. +They constrain responsibilities and behavior, not personal taste. A demonstrated +problem in a rule is a reason to review the rule, not to conceal or ignore a failure. + +## Ways to contribute + +- **Report a bug:** use the existing issue form. Include the version/build, OS, + display scale, relevant settings, minimal steps, expected result and actual result. + Search existing issues first. Remove tokens, credentials, private paths and command + history from logs or recordings before sharing them. +- **Propose a feature:** describe the workflow and user need before prescribing an + implementation. For broad changes, agree on scope before writing a large PR. +- **Translate or improve docs:** follow the language registry/catalog contract; + preserve named placeholders and review terminology, clipping and fallback. Do not + mark a language complete merely because English placeholders were copied into it. +- **Fix or test code:** start with a focused regression and an existing module's + tests. Add fixtures or improve coverage when that is the actual contribution. + +No programming contribution is required to be useful. Clear reproduction steps, +native-language review and accessibility feedback also help the project. + +## First code contribution + +1. Fork the existing `Kuddev/nebula` repository and create your work branch from the + PR target branch. See [INSTALL.md](INSTALL.md) for environment prerequisites. +2. Use the pinned Rust toolchain in `rust-toolchain.toml`. Build the actual GPUI + product, not an accidentally substituted legacy executable: + + ```sh + cargo build --locked -p nebula --bin nebula --features gpui-shell + ``` + +3. Make the focused change, run the checks below, and open a PR against the agreed + target. Draft PRs are useful for early design feedback; describe remaining work. +4. Respond to review and rerun affected checks after changes. Maintainers decide + readiness from the actual evidence, not from checked boxes alone. + +Do not include build outputs, local probes, screenshots containing secrets or +unrelated generated files. Preserve third-party license/attribution notices and +identify the source of any externally copied code or assets for license review. + +Keep one-off test scripts and probe outputs under `tmp/`; external project checkouts +and investigation notes belong in the reserved `research/`, `reference-projects/` +or `external-probes/` local directories. These are not vendored build dependencies: +do not blanket-ignore `third_party/` or maintained test/diagnostic sources. `docs/` +is private by default; public documentation needs an exact reviewed allowlist entry +in `.gitignore`. Do not publish competitor studies or HTML prototypes by opening a +whole documentation subtree. Ignore rules do not untrack files already in Git; +raise any existing tracked private artifact for an explicit maintainer decision. + +## Small, reviewable changes + +1. State the user-visible problem and the behavior to preserve. Discuss a new + cross-layer dependency, persisted format, core abstraction or threading model + before implementing it. Record significant decisions in the decision log. +2. Keep one conceptual change per PR. A necessary extraction and its behavior + tests may accompany the feature; unrelated rewrites and formatting may not. +3. Put shared rules in their existing authority. UI modules adapt those rules; + they must not fork persistence, state transitions or domain behavior. +4. Add regression tests that fail for the defect, and test error/cancellation + paths where relevant. Explain what was actually run and what was not. +5. Fill in the PR template. A green build is necessary, not sufficient: a + maintainer must also review cohesion, public interfaces, compatibility and cost. + +## Local checks + +The fast checker requires Python 3.11+ and no third-party Python packages. Use +`python` instead of `python3` on Windows if that is your configured interpreter. +Use the actual target branch commit, not the feature branch's own HEAD, for PR +ratcheting. Run without `--base` for current-tree checks during development. + +```sh +python3 scripts/check_architecture.py --base +python3 -m unittest scripts.tests.test_architecture_budgets scripts.tests.test_architecture_dependencies scripts.tests.test_architecture_governance +cargo test --manifest-path tools/i18n-contract/Cargo.toml --locked +cargo test -p nebula-settings +cargo test -p nebula --test file_line_budget +cargo fmt --all -- --check +``` + +Run affected behavior tests and the appropriate real product checks as well: + +```sh +cargo check -p nebula --bin nebula --features gpui-shell --tests --locked +``` + +The isolated i18n test compiles production files, not copied implementations. It +does not test real window layout, every OS integration, or the full application. +Existing platform build/package checks still apply. Never turn a metadata-only +compile check into a claim that UI tests or a packaged application were run. + +## Review and enforcement + +`architecture-contracts` is the stable PR job name. Maintainers must enable it as +a required check and require Code Owner approval in the target branch ruleset; +see the [activation checklist](docs/project-constraints.md#server-side-activation). +Local hooks are convenient, but bypassable; they are not the enforcement boundary. +Submitting a workflow or `CODEOWNERS` file does not configure server-side rules. + +Do not silence a failing contract by increasing a budget, removing test coverage, +compressing code, adding `continue-on-error`, or broadening an exclusion. If the +contract is wrong, submit a focused policy fix with a reproducer and both positive +and negative tests. Review a justified policy change separately from unrelated +feature work; there is no routine `--skip-architecture` option. + +## 中文摘要 + +- 先读架构图、工程合同和决策记录;按职责拆分,不按行号切片。 +- 2000 行是现有仓库的防灾上限,800 行只提示审查,不是“大厂标准”。 +- 普通功能 PR 不得增加存量债务;有问题的规则可以修订,但要有反例、测试和维护者审批。 +- 新增核心抽象、依赖方向、持久化或线程模型改变要先说明设计,不强迫每个小修复写 ADR。 +- 修改热路径要给出成本证据;不能为了“可扩展”增加没有实际用途的框架。 +- PR 要附实际测试结果;本地钩子和勾选框不代替服务端必需检查与人工评审。 diff --git a/INSTALL.md b/INSTALL.md index 0fbdc18..8a6d4a4 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -1,4 +1,8 @@ -# Installing Nebula +# Installing Pebrel + +Pebrel retains the `Kuddev/nebula` repository, `nebula` command, and existing +package identifiers for compatibility. Historical download filenames below +are unchanged; do not rename installed files or configuration directories. ## Linux Preview diff --git a/README.md b/README.md index b680fa0..19b9b75 100644 --- a/README.md +++ b/README.md @@ -4,9 +4,7 @@

Pebrel

-> **Local branding preview / 本地品牌预览** — Pebrel is the new display name of Nebula Terminal. This worktree keeps version 1.5.0, `nebula.exe`, existing configuration paths, installer identity, and the Nebula update feed for compatibility. Pebrel-named packages are local test artifacts, not a new GitHub Release. Installing the setup package targets the existing Nebula installation; use the ZIP with isolated configuration for side-by-side testing. -> -> Pebrel 是 Nebula Terminal 的新展示名称。本工作区保留 1.5.0 版本、`nebula.exe`、现有配置路径、安装标识和 Nebula 更新源,以维持兼容。Pebrel 命名的包仅用于本地测试,不代表新的 GitHub Release。安装器沿用现有 Nebula 安装身份;需要并行测试时,请使用 ZIP 并配置隔离目录。 +Contributing / 参与贡献:[Guide / 指南](CONTRIBUTING.md) · [Architecture / 架构](docs/architecture.md) · [Engineering contracts / 工程规范](docs/project-constraints.md)

A GPU-accelerated terminal for Windows that keeps your sessions alive — close the window, your claude conversation survives.
@@ -33,16 +31,16 @@

- Nebula Terminal horizontal title-bar tabs and translucent background + Pebrel horizontal title-bar tabs and translucent background

- Claude Code running in Nebula Terminal + Claude Code running in Pebrel

- Nebula Terminal with OpenCode, Claude Code, and Codex in split panes + Pebrel with OpenCode, Claude Code, and Codex in split panes

--- @@ -63,7 +61,7 @@ experience that works without extra setup. - **Session residency** — closing the window *detaches* instead of killing: every PTY (your running `claude`, builds, SSH sessions) keeps running in a - resident process. Launch Nebula again and the window re-attaches — same + resident process. Launch Pebrel again and the window re-attaches — same processes, same scrollback, mid-conversation. - **Cold session restore** — if the resident process is gone (reboot, crash), the next launch still restores your tab layout and per-tab working @@ -83,14 +81,14 @@ experience that works without extra setup. actual Anthropic starburst; `codex` shows the OpenAI blossom, tinted to the theme. Other programs get Nerd Font icons (`gemini`, `copilot`, `git`, `vim`, `cargo`, …). -- **Live turn state, wired to the source** — Nebula installs Claude Code +- **Live turn state, wired to the source** — Pebrel installs Claude Code hooks (and Codex notify) pointing at a bundled bridge (`nebula-hook.exe`, dependency-free): prompt submitted → spinner; turn finished → dot + toast; Claude needs your input → toast carrying the actual message text. Delivered over a local named pipe, with no shell integration required. - **Click-to-focus notifications** — every toast knows which pane raised it: - click one and Nebula comes to the foreground, switches to that tab and + click one and Pebrel comes to the foreground, switches to that tab and focuses that split. - **Zero setup, self-healing** — the hook entries install on first boot and re-install themselves if a config switcher rewrites the file (a watcher on @@ -98,11 +96,11 @@ experience that works without extra setup. running in any other terminal is untouched. `nebula setup-ai --remove` undoes everything. - **Plays nice with existing notifiers** — codex has a single notify slot; - Nebula wraps it (`--chain`) instead of stealing it, so a pre-existing + Pebrel wraps it (`--chain`) instead of stealing it, so a pre-existing notifier keeps firing. - **Fallback signals** — OSC 133 command tracking + BEL still cover every other CLI: long builds toast on completion, with their duration. -- **Native SSH sessions** — saved hosts open directly through Nebula's Rust SSH +- **Native SSH sessions** — saved hosts open directly through Pebrel's Rust SSH transport: no wrapper shell and no external console window. Host aliases, usernames, ports and identity files are resolved from `~/.ssh/config`; authentication supports standard private keys and certificates, encrypted-key @@ -116,14 +114,14 @@ experience that works without extra setup. folders, recursively delete, follow symlink targets, and cancel transfers with visible progress and errors. - **AI-aware over SSH** — remote Hook envelopes can return through a - per-channel, randomly authenticated private OSC bridge. Nebula validates the + per-channel, randomly authenticated private OSC bridge. Pebrel validates the channel token, replaces any remote pane identifier with the local pane, and routes the event through the existing sidebar and Windows notification path. The `nebula ssh` compatibility command remains available for forwarding, query and explicit-command forms that need the system SSH client.

- Nebula native SSH session + Pebrel native SSH session

**Performance & correctness** @@ -153,7 +151,7 @@ experience that works without extra setup. **Markdown that renders like GitHub**

- Nebula rendering its own README: centred logo, badge row, and an embedded screenshot + Pebrel rendering its own README: centred logo, badge row, and an embedded screenshot

- **Markdown/GFM document tabs** — open Markdown, JSON, and plain-text files @@ -162,7 +160,7 @@ experience that works without extra setup. - **Images from anywhere** — remote `http(s)` URLs, `data:` URIs, absolute paths, and paths relative to the document all resolve, so badge rows, logos, and embedded screenshots land exactly where the file puts them. The - screenshot above is Nebula rendering its own README. + screenshot above is Pebrel rendering its own README. - **The HTML that real READMEs use** — `

` centres its content, several `` badges in one paragraph stay on a single row instead of breaking into separate blocks, `
` breaks in document order, and @@ -174,7 +172,7 @@ experience that works without extra setup. **Documents & native mathematics**

- Native mathematics rendered in a Nebula Markdown document + Native mathematics rendered in a Pebrel Markdown document

- **Native TeX mathematics** — inline `$...$` and display `$$...$$` formulas @@ -214,15 +212,15 @@ experience that works without extra setup. ### 📥 Install -> **⚠️ Install the bundled font first.** Nebula's powerline prompt, program +> **⚠️ Install the bundled font first.** Pebrel's powerline prompt, program > icons and AI brand marks are drawn with **Maple Mono Normal NF CN** (a Nerd Font). -> Nebula embeds the same font as a runtime fallback so forgetting to install it +> Pebrel embeds the same font as a runtime fallback so forgetting to install it > no longer breaks the interface, but a normal system installation is still the > intended setup. The font ships in the release zip under `fonts/` and the repo at > `assets/fonts/MapleMonoNormal-NF-CN-Regular.ttf` — double-click -> it and press **Install**, then launch Nebula. Nebula checks the font on every +> it and press **Install**, then launch Pebrel. Pebrel checks the font on every > launch; if the system font is missing, a dismissible reminder can open the -> bundled `fonts/` folder. Install the font and restart Nebula for the complete +> bundled `fonts/` folder. Install the font and restart Pebrel for the complete > icon set. (Licensed under SIL OFL 1.1.) **Release build (recommended)** — download @@ -241,7 +239,7 @@ cargo build --release # artifacts land in target/release/ ### Lua Configuration -Nebula ships a vendored Lua 5.4 runtime with `require 'nebula'` and +Pebrel ships a vendored Lua 5.4 runtime with `require 'nebula'` and `nebula.config_builder()`. Generate an annotated template with `nebula config init --language system|zh-CN|en-US`, then validate it without opening the GUI using `nebula config check`. Module `require` paths participate @@ -273,25 +271,25 @@ Questions and feedback: [fickleheartedkeys@163.com](mailto:fickleheartedkeys@163 ### 🙏 Acknowledgements -Nebula's terminal core — the grid, the VTE escape-sequence parsing, and the PTY +Pebrel's terminal core — the grid, the VTE escape-sequence parsing, and the PTY plumbing — is derived from **[Alacritty](https://github.com/alacritty/alacritty)**, a masterpiece of terminal engineering. Sincere thanks to its maintainers and contributors; -Nebula would not exist without their work. +Pebrel would not exist without their work. -Nebula's shell is built on **[GPUI](https://github.com/zed-industries/zed)** — the +Pebrel's shell is built on **[GPUI](https://github.com/zed-industries/zed)** — the GPU-accelerated UI framework developed by the [Zed](https://zed.dev) team — together with **[gpui-component](https://github.com/longbridge/gpui-component)** from [Longbridge](https://github.com/longbridge), which supplies the widget library. Both are Apache-2.0 licensed and are used through lightly patched forks pinned in the workspace -manifest. Thank you for releasing this work as open source — Nebula's interface would not +manifest. Thank you for releasing this work as open source — Pebrel's interface would not look the way it does without it. ### 📜 License Released under the [GNU General Public License v3.0](LICENSE). -Parts of Nebula are derived from upstream open-source projects; their original +Parts of Pebrel are derived from upstream open-source projects; their original license and copyright notices are preserved in [THIRD-PARTY-NOTICES](THIRD-PARTY-NOTICES). The work as a whole is distributed under GPL-3.0. @@ -312,7 +310,7 @@ Pebrel(原名 Nebula)是一款 Windows 上的终端模拟器,以 Rust 编 **会话永生** - **会话驻留** — 关闭窗口是*分离*而不是杀死:所有 PTY(正在跑的 - `claude`、构建、SSH)继续在常驻进程里运行。再次启动 Nebula,窗口原样接回 + `claude`、构建、SSH)继续在常驻进程里运行。再次启动 Pebrel,窗口原样接回 —— 同样的进程、同样的回滚缓冲、对话进行到一半也不丢。 - **冷恢复** — 常驻进程不在了(重启、崩溃)也没关系:下次启动从持续自动保 存的快照恢复标签布局和每个标签的工作目录,并带崩溃循环保护。 @@ -328,20 +326,20 @@ Pebrel(原名 Nebula)是一款 Windows 上的终端模拟器,以 Rust 编 - **侧栏显示真品牌标识** — 跑 `claude` 的标签显示 Anthropic 珊瑚星芒, `codex` 显示 OpenAI 花结(贴图渲染、跟随主题染色);其余程序用 Nerd Font 图标(`gemini`、`copilot`、`git`、`vim`、`cargo`……)。 -- **回合状态实时直连** — Nebula 自动安装 Claude Code hooks(及 Codex +- **回合状态实时直连** — Pebrel 自动安装 Claude Code hooks(及 Codex notify),指向随包的桥接器 `nebula-hook.exe`(无第三方依赖): 提交 prompt → 转圈;回合完成 → 圆点 + 通知;claude 要你确认 → 通知里 带消息原文。经本地命名管道传递,无需任何 shell 集成。 -- **通知点击直达** — 每条 toast 都知道自己来自哪个 pane:点一下,Nebula +- **通知点击直达** — 每条 toast 都知道自己来自哪个 pane:点一下,Pebrel 前置、切到那个标签、聚焦那个分屏。 - **零配置、自愈合** — hook 条目首次启动自动写入;被配置切换工具覆盖后 会自动补回(配置目录上有监视器重新写入)。作用域由环境变量限定:其他 终端里的 claude 完全不受影响。`nebula setup-ai --remove` 一键撤销。 -- **不抢占已有 notifier** — codex 只有一个 notify 槽位,Nebula 用 +- **不抢占已有 notifier** — codex 只有一个 notify 槽位,Pebrel 用 `--chain` 包装而非顶掉:原有通知程序照常触发。 - **兜底信号** — OSC 133 命令跟踪 + BEL 覆盖其余所有 CLI:长构建完成也 弹通知,并带耗时。 -- **原生 SSH 会话** — 保存的主机现在直接通过 Nebula 的 Rust SSH 传输连接, +- **原生 SSH 会话** — 保存的主机现在直接通过 Pebrel 的 Rust SSH 传输连接, 不再经过包装 Shell,也不会弹出外部控制台窗口。主机别名、用户名、端口和 IdentityFile 会从 `~/.ssh/config` 解析;认证覆盖标准私钥与证书、加密密钥 口令、Windows 凭据管理器密码以及 keyboard-interactive/MFA。主机密钥写入 @@ -351,12 +349,12 @@ Pebrel(原名 Nebula)是一款 Windows 上的终端模拟器,以 Rust 编 连接。支持浏览或手动输入远端路径、筛选、上传/下载文件与文件夹、新建与重命名 文件夹、递归删除、跟随符号链接目标,以及带进度、取消和错误提示的后台传输。 - **SSH 里也 AI 感知** — 远端 Hook 信封可通过每通道随机认证的私有 OSC 桥 - 返回。Nebula 会校验通道令牌,用本地 Pane 身份覆盖远端字段,再复用现有侧栏 + 返回。Pebrel 会校验通道令牌,用本地 Pane 身份覆盖远端字段,再复用现有侧栏 状态和 Windows 通知链路。需要端口转发、配置查询或显式远程命令时,仍可使用 `nebula ssh` 兼容命令交给系统 SSH 客户端处理。

- Nebula 原生 SSH 会话 + Pebrel 原生 SSH 会话

**性能与正确性** @@ -382,14 +380,14 @@ Pebrel(原名 Nebula)是一款 Windows 上的终端模拟器,以 Rust 编 **Markdown 解析:照着 GitHub 的样子显示**

- Nebula 正在渲染自己的 README:居中 logo、徽章横排、内嵌截图 + Pebrel 正在渲染自己的 README:居中 logo、徽章横排、内嵌截图

- **Markdown/GFM 文档标签页** — 可以从文件抽屉直接打开 Markdown、JSON 和 纯文本文件,原生显示标题、列表、表格、代码块、链接、引用、自动换行和虚拟滚动。 - **图片来源不挑** — 远程 `http(s)` 链接、`data:` URI、绝对路径,以及相对文档 自身位置的路径都能解析,徽章行、logo 和内嵌截图都落在文件让它们出现的地方。 - 上面这张图就是 Nebula 在渲染自己的 README。 + 上面这张图就是 Pebrel 在渲染自己的 README。 - **真实 README 会用到的那些 HTML** — `

` 居中生效,同一段里 的多枚 `` 徽章横排显示而不会被拆成若干块,`
` 按文档顺序断行, `` 形式的链接徽章不会整个丢失。 @@ -399,7 +397,7 @@ Pebrel(原名 Nebula)是一款 Windows 上的终端模拟器,以 Rust 编 **文档与原生数学公式**

- Nebula Markdown 文档中的原生数学公式 + Pebrel Markdown 文档中的原生数学公式

- **原生 TeX 数学排版** — 行内 `$...$` 与块级 `$$...$$` 公式全部由 Rust @@ -432,14 +430,14 @@ Pebrel(原名 Nebula)是一款 Windows 上的终端模拟器,以 Rust 编 ### 📥 安装 -> **⚠️ 请先安装随附字体。** Nebula 的 powerline 提示符、程序图标与 AI 品牌 -> 标识都用 **Maple Mono Normal NF CN**(一款 Nerd Font)绘制。Nebula 已把同一字体 +> **⚠️ 请先安装随附字体。** Pebrel 的 powerline 提示符、程序图标与 AI 品牌 +> 标识都用 **Maple Mono Normal NF CN**(一款 Nerd Font)绘制。Pebrel 已把同一字体 > 内置为运行时兜底,忘记安装也不会再让界面显示异常,但正常使用仍建议安装到系统。 > 字体在 release 包内、仓库里也有: > `assets/fonts/MapleMonoNormal-NF-CN-Regular.ttf`;压缩包内位于 `fonts/` —— > 双击它点**安装**,再启动 -> Nebula。Nebula 每次启动都会检查系统字体;如果还没有正确安装,会显示一个 -> 可关闭的提醒,并提供“打开字体文件夹”按钮。安装完成后重启 Nebula 即可显示完整图 +> Pebrel。Pebrel 每次启动都会检查系统字体;如果还没有正确安装,会显示一个 +> 可关闭的提醒,并提供“打开字体文件夹”按钮。安装完成后重启 Pebrel 即可显示完整图 > 标。(SIL OFL 1.1 许可。) **Release 包(推荐)** — 从 @@ -457,7 +455,7 @@ cargo build --release # 产物在 target/release/ ### Lua 配置 -Nebula 内置 Lua 5.4,使用 `require 'nebula'` 与 +Pebrel 内置 Lua 5.4,使用 `require 'nebula'` 与 `nebula.config_builder()`。运行 `nebula config init --language system|zh-CN|en-US` 可生成带完整注释的模板, `nebula config check` 可在不启动 GUI 的情况下检查语法与字段。通过 `require` @@ -488,22 +486,22 @@ Nebula 内置 Lua 5.4,使用 `require 'nebula'` 与 ### 🙏 致谢 -Nebula 的终端内核——网格、VTE 转义序列解析与 PTY 管路——衍生自 +Pebrel 的终端内核——网格、VTE 转义序列解析与 PTY 管路——衍生自 **[Alacritty](https://github.com/alacritty/alacritty)**,终端工程的杰作。 -衷心感谢它的维护者与贡献者们;没有他们的工作就没有 Nebula。 +衷心感谢它的维护者与贡献者们;没有他们的工作就没有 Pebrel。 -Nebula 的界面层构建在 **[GPUI](https://github.com/zed-industries/zed)** 之上——由 +Pebrel 的界面层构建在 **[GPUI](https://github.com/zed-industries/zed)** 之上——由 [Zed](https://zed.dev) 团队开发的 GPU 加速 UI 框架——并使用 [Longbridge](https://github.com/longbridge) 的 **[gpui-component](https://github.com/longbridge/gpui-component)** 作为组件库。两者均以 -Apache-2.0 许可发布,Nebula 通过带少量补丁的 fork 使用,版本在 workspace 清单中精确锁定。 -感谢把这些工作开源——没有它,Nebula 现在的界面不会是这个样子。 +Apache-2.0 许可发布,Pebrel 通过带少量补丁的 fork 使用,版本在 workspace 清单中精确锁定。 +感谢把这些工作开源——没有它,Pebrel 现在的界面不会是这个样子。 ### 📜 许可证 基于 [GNU 通用公共许可证 v3.0(GPL-3.0)](LICENSE) 发布。 -Nebula 的部分代码衍生自上游开源项目,其原始许可与版权声明保留于 +Pebrel 的部分代码衍生自上游开源项目,其原始许可与版权声明保留于 [THIRD-PARTY-NOTICES](THIRD-PARTY-NOTICES)。整体作品以 GPL-3.0 分发。 --- diff --git a/docs/architecture-decisions.md b/docs/architecture-decisions.md new file mode 100644 index 0000000..8613e25 --- /dev/null +++ b/docs/architecture-decisions.md @@ -0,0 +1,60 @@ +# Architecture decisions / 架构决策记录 + +## Process + +Record decisions that change dependency direction, core ownership, persistent +interfaces, threading/lifetime, performance contracts or governance itself. Do not +require a new record for each typo or ordinary bug fix. Records are reviewable; +an accepted decision may be superseded when evidence changes. + +Use: **Status; Context; Evidence; Decision; Alternatives; Consequences; Validation; +Revisit condition.** Identify the accountable maintainer in the PR review. A policy +change must include a failing legitimate example when correcting a false positive, +plus a violation that must remain rejected. Do not use a policy edit to conceal an +unrelated feature's growth. Remote approval/enforcement is not implied by this log. + +## ADR-0001 — Evidence-based architecture contracts + +- **Status:** Adopted in the working-tree implementation, 2026-09-05; pending normal + repository review and server-side activation. Initial owner entry: `@Kuddev`. +- **Context:** Multiple rendering adapters share behavior; a large contribution + volume needs stable boundaries. Existing source-size documentation was ignored + by Git and the old scanner could inspect local build/probe artifacts. +- **Evidence:** [Primary-source review](engineering-evidence.md), workspace manifests, + feature-selected module aliases, and positive/negative checker fixtures. +- **Decision:** Keep the modular application and 2000-line hard / 800-line advisory + limits. Share a precise legacy inventory, enforce production crate directions, + and verify pure i18n independently. Review module cohesion and lifecycle manually. +- **Alternatives rejected:** An abrupt 800-line hard limit (65 additional oversized + legacy files); import-name blacklists (incorrect under `#[path]`/cfg); mandatory + microservices/traits; machine-specific nanosecond CI thresholds. +- **Consequences:** Ordinary PRs cannot silently expand debt. Large legacy changes + may require a responsibility extraction. Valid source-layout or policy changes + can require an explicit governance update and new fixtures, not a skip flag. +- **Validation:** The checker suite covers legitimate and forbidden dependencies, + base ratcheting, paths, parsing and scan errors. CI runs those tests before using + the checker. Real product compilation and human review remain separate evidence. +- **Revisit condition:** A reproducible legitimate change is rejected, the source + layout changes, or measured review cost outweighs a threshold's benefit. Correct + the narrow rule with tests; do not treat this ADR as immutable proof of quality. + +## ADR-0002 — Static extensible UI translation + +- **Status:** Implemented in the working tree, 2026-09-05; not a new release claim. +- **Context:** Shared language choices and translations must not add parsing, + locking or string allocation to ordinary UI text lookup. +- **Decision:** One registry, build-time validated catalogs, typed static lookups, + English fallback for partial locales, and a separate parameter-formatting path. +- **Consequences:** Adding a language is a registry/catalog change and requires a + build. Initial coverage is partial; live downloadable language packs and complete + locale-aware formatting are not promised. +- **Validation:** Compile production lookup/generator code in the isolated contract + workspace; test invalid catalogs, fallback, locale matching and zero allocations. +- **Revisit condition:** A real requirement for runtime packs, richer plural/date + formatting or RTL layouts warrants a separately measured design. See the + [internationalization contract](internationalization.md). + +## 中文说明 + +记录重大取舍而非每次小修复;事实与测试能推翻旧决定。规范误伤、安全修复与旧预算冲突时, +先记录问题和最小修订,维护者审查后更新合同;不能将“只减不增”变成拒绝纠正规范的理由。 diff --git a/docs/architecture.md b/docs/architecture.md new file mode 100644 index 0000000..d144968 --- /dev/null +++ b/docs/architecture.md @@ -0,0 +1,99 @@ +# Pebrel architecture / 架构地图 + +## Shape: modular desktop application + +Keep a modular monolith: domain rules and adapters communicate inside the desktop +application unless a current lifecycle or isolation requirement justifies another +process. Existing mux, CLI hook and acceptance-lab processes have concrete roles; +they are not a reason to introduce generic microservices or a service locator. + +The dependency direction is **composition/UI → application capabilities → shared +domain rules**. Platform and I/O details adapt domain inputs/results. They must not +make a domain crate depend on a view. This is a responsibility model, not a demand +to rename all existing directories or create abstract interfaces everywhere. + +## Current ownership map + +| Area | Owns | Must not become | +| --- | --- | --- | +| `nebula_settings` | Runtime settings, language registry, shared preference contracts | A UI/widget library | +| `nebula_split` | Split tree, geometry, navigation rules | Window management or rendering | +| `nebula_terminal` | Grid, VT processing, terminal/PTY behavior | Product panels or GPUI state | +| `nebula_config`, `nebula_config_derive` | Configuration abstractions and derives | Application orchestration | +| `nebula-completions` | Completion matching and presentation-independent results | Terminal view ownership | +| `nebula_hook` | Small process/lifecycle hook bridge | An application dependency container | +| `nebula_app/src/i18n` | Static lookup, locale resolution and formatting | Runtime catalog parsing or UI ownership | +| `nebula_app/src/math` | Parse, validate, layout, compile and cache responsibilities | A duplicated per-shell math engine | +| `nebula_app/src/platform` | Explicit platform capabilities and native adapters | A dumping ground for unrelated logic | +| `nebula_app/src/gpui_shell` | GPUI views, UI state, commands and subscriptions | A second settings/domain implementation | +| `nebula_app/src/product_ui` | Feature-selected shared presentation facade | A route to legacy rendering dependencies | +| `nebula_app/src/display`, `renderer` | Legacy rendering and still-shared extracted models | A source of new undifferentiated functionality | +| `nebula_gpui` | Component acceptance lab | A dependency of the product | +| `nebula_app/build`, `tools/i18n-contract` | Generation and independent contract verification | Runtime configuration loading | + +The map records current responsibilities; it does not assert that every legacy +file has already reached the target shape. Eleven oversized legacy files remain +under [ratcheted budgets](project-constraints.md). Move their independent rules +when working on the relevant capability; do not mix a whole-app rewrite into a fix. + +## Rust module names are not file locations + +`main.rs` selects `product_ui/mod.rs` as the `display` module when the legacy shell +is disabled. It likewise selects product adapters for several legacy-looking paths. +The product facade currently reuses extracted models via `#[path]` declarations. +`i18n/outcomes.rs` is compiled as the separate root module `localized_status`. + +Consequently, neither an import containing `display` nor a file beneath that folder +proves that the product loads the legacy renderer. Keep semantic boundaries tested +with the actual feature configuration. Avoid relocating code merely to satisfy a +string-matching architecture tool. + +## Feature modules and lifecycle + +For a capability that grows, prefer a small entry/facade plus cohesive child modules: + +```text +capability/ + mod.rs exposed operations and orchestration + model.rs owned state and transitions, when substantial + adapter.rs I/O/platform conversion, when needed + view.rs renderer-specific presentation, when needed + tests.rs behavior contracts/fixtures, when substantial +``` + +This is a possible shape, not a mandatory directory scaffold. Name children after +their real responsibility (`navigation`, `shell_picker`, `parser`, `layout`), not +`part1`, `common2` or `misc`. A short cohesive module can stay a single file. Keep +orchestration readable; it should not absorb every callback, parser and widget. + +Cross-feature calls should use deliberately exposed commands/results rather than +mutating another feature's internal collections. Prefer concrete types and plain +functions until a second real implementation, testing seam or native boundary +justifies a trait. Do not make fields public simply to make extraction compile. + +Background work carries an owning scope and cancellation/staleness policy. Results +must be applied only to a still-valid view/session. Renderer callbacks should use +prepared state, not synchronously reload preferences, scan disks or wait for a child +process. Measure hot-path effects instead of extrapolating a tiny benchmark to the +whole product. + +## Extension checklist + +- New setting: shared registry/model → persistence contract → shell adapter → tests. +- New language: one registry row + catalog; reuse static generation and fallback. +- New panel: put presentation under the shell, reuse existing domain operations. +- New platform support: model the capability, then implement a native adapter; + unsupported behavior must be explicit, not a silently successful stub. +- New dependency/crate/long-lived service: first document its responsibility, + direction, cost, ownership and why an existing module is insufficient. + +See [CONTRIBUTING](../CONTRIBUTING.md), [enforced contracts](project-constraints.md), +and [decision records](architecture-decisions.md). Architectural review evaluates +cohesion and knowledge shared across boundaries; CI provides narrower mechanical +checks, not a guarantee against every future design mistake. + +## 中文摘要 + +坚持模块化桌面应用:界面负责呈现与编排,领域规则有唯一权威实现,平台和 I/O 放在明确适配边界。 +按能力、状态归属和生命周期分组,不为了“可扩展”先造微服务、全局容器或层层 trait。 +拆文件必须减少跨模块知识,不以文件数增加作为解耦证明;旧大文件按相关功能逐步治理。 diff --git a/docs/engineering-evidence.md b/docs/engineering-evidence.md new file mode 100644 index 0000000..198bd1a --- /dev/null +++ b/docs/engineering-evidence.md @@ -0,0 +1,53 @@ +# Engineering policy evidence / 规范依据 + +Reviewed on **2026-09-05** using primary sources and an independent repository +review. Mature projects support these principles, not the claim that our exact +checker or numerical limits are universally correct. No source below establishes +800 or 2000 as the optimal size of every source file. + +| Primary source | What it supports | What we deliberately do not infer | +| --- | --- | --- | +| [Google: review standard](https://google.github.io/eng-practices/review/reviewer/standard.html) | Technical facts and evidence should outweigh personal preference; improve code health | A reviewer's preferred structure is automatically mandatory | +| [Google: what to review](https://google.github.io/eng-practices/review/reviewer/looking-for.html) | Review design, complexity, tests and over-engineering | Every possible future extension needs an abstraction now | +| [Google: small changes](https://google.github.io/eng-practices/review/developer/small-cls.html) | Keep changes conceptually focused and reviewable | PR-size guidance proves a universal file-line threshold | +| [VS Code: source organization](https://github.com/microsoft/vscode/wiki/Source-Code-Organization) | A large desktop editor uses explicit layers and module responsibilities | Pebrel must copy VS Code's names, process model or entire framework | +| [Android: modularization patterns](https://developer.android.com/topic/modularization/patterns) | Balance high cohesion and low coupling; choose meaningful module boundaries | More modules or files always means better decoupling | +| [Android: lint baseline](https://developer.android.com/studio/write/lint#create-baseline) | Treat existing findings separately while stopping new regressions | Every old file must be rewritten before a small fix can merge | +| [Chromium: layering cookbook](https://www.chromium.org/developers/design-documents/cookbook/) | Separate reusable core from host-specific code; verify dependency checks actually run | A successful empty scan or path-name regex proves sound architecture | +| [Cargo: dependency sources](https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html) and [dev cycles](https://doc.rust-lang.org/cargo/reference/resolver.html#dev-dependency-cycles) | Package identity/source matters; some dev cycles are legal | All dependency graph cycles should be mixed into one prohibition | +| [Rust: modules](https://doc.rust-lang.org/reference/items/modules.html) | Module paths and file paths can differ with attributes | `crate::display` necessarily refers to the legacy renderer | +| [Microsoft: decision log](https://microsoft.github.io/code-with-engineering-playbook/design/design-reviews/decision-log/) | Record consequential architecture decisions and their context | ADRs should be immutable or required for every trivial edit | +| [GitHub: code owners](https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners) | Ownership and protected-branch review requirements work together | Adding `CODEOWNERS` alone makes approvals mandatory | +| [GitHub: required checks](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/collaborating-on-repositories-with-code-quality-features/troubleshooting-required-status-checks) | Required checks must actually run; skipped filtered workflows can remain pending | A path-filtered docs-only PR always receives a usable required status | +| [GitHub: secure workflow use](https://docs.github.com/en/actions/security-for-github-actions/security-guides/security-hardening-for-github-actions) | Treat contributor code and event input as untrusted | A privileged `pull_request_target` job should execute arbitrary PR code | + +## Local evidence and resulting changes + +- Initial inventory: 76 Rust files exceeded 800 lines; only 11 exceeded 2000. + Making 800 a hard gate would add 65 legacy exceptions. We retain the existing + hard ceiling and make the smaller number a nonblocking review aid. +- The existing settings/split/hook manifests explicitly preserve low-dependency + production roles. The new policy preserves those concrete contracts, without + banning legitimate test-only tools on runtime-performance grounds. +- Feature aliases in `main.rs` and `product_ui/mod.rs` disprove a simple forbidden + `display` import rule. We check declared local crate dependencies and real + compilation instead of pretending to resolve Rust with a regex. +- Independent adversarial fixtures exposed an empty-base bootstrap bug, ancestor + symlink traversal and false classification of an external same-named package. + These cases became regression tests before adopting the checker. +- Historic platform-cfg counting misclassifies comments/strings and some nested + expressions. It is not used as proof of decoupling or promoted into this gate. + +## Confidence and limits + +The assurance is narrow: the declared contracts have executable positive/negative +tests and CI wiring. The assurance is not that all future architecture is good, +that all translations are complete, or that GitHub protection is already enabled. +Maintainers must review rule changes and verify the remote activation checklist. + +Review this evidence when changing a rule, not by calendar ritual alone. A numerical +threshold should be revised when repository evidence warrants it; cohesion and +compatibility are the objectives, not winning a line-count metric. + +中文:采用成熟实践中的分层、增量基线与负责人审查,但不照搬数字、不把正则当语义分析。 +门禁自己也有正反测试;能够复现的误报必须修正,而不是让后来的贡献者适应错误规范。 diff --git a/docs/internationalization.md b/docs/internationalization.md new file mode 100644 index 0000000..8ac544e --- /dev/null +++ b/docs/internationalization.md @@ -0,0 +1,112 @@ +# Pebrel internationalization / 多语言架构 + +## Scope / 范围 + +The project uses the Pebrel name while retaining the `Kuddev/nebula` GitHub +repository and existing CLI, configuration, installer, and update identifiers. +Renaming those compatibility interfaces is a separate migration, not a text replacement. + +项目名称采用 Pebrel,GitHub 仓库保留 `Kuddev/nebula`。CLI、配置、安装及更新标识 +属于兼容接口,不随展示名称机械替换。 + +The first language set is English, Simplified Chinese, Traditional Chinese, +French, German, Spanish, Brazilian Portuguese, Italian, Russian, Japanese, and +Korean. The picker displays each language's native name. POSIX locale suffixes, +regional variants, and Chinese Hans/Hant scripts are negotiated at language resolution. +Terminal subprocess output and environment variables are not translated or overridden. + +首批语言为英语、简体中文、繁体中文、法语、德语、西班牙语、巴西葡萄牙语、意大利语、 +俄语、日语及韩语。选择器使用语言自称,并在解析语言时处理 POSIX 后缀、地区变体及 +中文 Hans/Hant。不会翻译终端子进程的输出,也不会覆盖它们的语言环境变量。 + +The initial catalogs cover navigation, common actions, appearance labels, and +network controls in all eleven languages. French also covers all existing +catalog-based diagnostics. Many older inline bilingual descriptions are not yet +migrated; they intentionally fall back to English. This is not a claim of complete +translation of every screen, configuration template, or installer language. + +初版词典覆盖全部十一种语言的导航、常用操作、外观标签与网络控件;法语同时覆盖原有 +词典中的诊断文案。大量旧的内联双语长说明尚未迁移,明确回退英文,不宣称所有页面、 +配置模板和安装向导已经完成全量翻译。后续翻译应经过母语审校。 + +## Runtime contract / 运行时合同 + +- `nebula_settings/src/language.rs` owns the supported-language registry, + native names, saved values, and locale negotiation. Both shells use it. +- `nebula_app/build/i18n.rs` validates JSON and generates static Rust data at + compile time. Runtime lookup never parses a JSON file, constructs a map, + reads a file, takes a lock, or allocates a string. +- `UiLanguage::text(Message::...)` uses a typed identifier and direct table + indexing. Use this for new UI code; missing identifiers fail compilation. +- `tr("stable.id")` is a compatibility interface using a generated string + match. Its fallback is target language → English → original key. +- Existing `pick(Chinese, English)` remains a migration bridge: Chinese and + English retain their immediate branches; other languages use an unambiguous + catalog match or English. Ambiguous English phrases do not borrow a translation + from the wrong context. New context-sensitive messages must use typed ids. +- Formatting is a separate path that builds a `String` only when arguments + are needed. Values are inserted literally, not recursively interpreted as + placeholders. Missing arguments stay visible; `{{` and `}}` escape braces. +- GPUI keeps the resolved language in application state. System locale + detection is outside text rendering. The pinned component library has a + smaller locale set; unsupported widget locales explicitly use English. + +核心原则:运行时只读编译好的静态表;新代码使用类型化 ID 直接索引;只有带参数的文案 +才创建字符串。旧 `tr` 和 `pick` 是渐进迁移入口,不应作为继续堆积双语硬编码的理由。 +组件库的语言覆盖与自有文案分开记录,不支持的组件语言明确使用英文,避免假装全量覆盖。 + +## Add a language / 新增语言 + +1. Add one row to the `languages!` registry in `nebula_settings/src/language.rs`. + Saved values are canonical locale tags; do not change existing tags or order. +2. Add `nebula_app/i18n/.json`. Keep the same message ids and named + placeholders as English. A partial catalog is allowed and falls back to English. + Do not copy English entries just to inflate the translation coverage count. +3. Set the component locale to one actually supplied by the pinned component + library, or use `en`. Do not claim right-to-left layout support without testing it. +4. Run the catalog, preference, UI-switching, and allocation tests. Review + long labels, font coverage, keyboard access, and the real UI with a native speaker. + +新增语言只需注册表一行及对应 JSON;选择器、语言枚举和运行时表由同一注册表生成, +无需在所有页面添加分支。构建会拒绝重复 ID、空字符串、未知 ID、非法叶子类型和占位符 +不一致;简中与英文基础词典必须完整对齐,其他语言可渐进补齐。 + +## Module boundaries / 解耦边界 + +- `src/i18n/`: renderer-independent lookup, locale resolution, formatting, and tests. +- `src/i18n/outcomes.rs`: presentation adapters for provider/proxy results; it is + compiled separately from the pure lookup core and does not move I/O into translation. +- `settings_pane/navigation.rs`: route, navigation, and display metadata. +- `settings_pane/localization.rs`: select values and translated labels. +- `settings_pane/status.rs`: semantic operation results rendered in the active language. +- `settings_pane/shell_picker.rs`: shell selector items and import boundary. +- `settings_pane/initialization.rs`: entity construction and event subscriptions. +- `settings_pane.rs`: pane state, orchestration, and rendering. + +这轮优先拆分语言与设置链路,不改变持久化格式、事件含义和设置生效时机。其他存量超大 +文件仍由行数预算约束,应在对应功能改动时按职责拆分,而不是为了行数任意切片。 + +## Checks / 验证 + +```text +cargo test -p nebula-settings +cargo test --manifest-path tools/i18n-contract/Cargo.toml --locked +cargo test -p nebula --test i18n_contract +cargo test -p nebula --bin nebula --features gpui-shell i18n:: +cargo test -p nebula --bin nebula --features gpui-shell gpui_shell::settings_pane::tests:: +cargo test -p nebula --test file_line_budget +cargo test -p nebula --test i18n_contract --release -- --ignored --nocapture +``` + +The allocation contract checks both the first and repeated lookup across every +language. The timing benchmark is informational, not a machine-dependent CI speed +threshold. The initial translated UTF-8 payload has a 256 KiB budget; string table +pointers and generated code are additional binary overhead, not included in that count. + +零分配测试覆盖首次与重复查词;微基准只报告实测值,不把某台机器的耗时写死成 CI 阈值。 +初版 UTF-8 翻译文本预算为 256 KiB;指针表与生成代码是额外开销,不冒充完整二进制体积。 + +The independent contract workspace compiles the production generator and lookup +files without renderer dependencies. The `architecture-contracts` PR job executes +it, while real GPUI/platform checks and native-language layout review remain separate. +Language or ownership changes also follow the [engineering contracts](project-constraints.md). diff --git a/docs/project-constraints.md b/docs/project-constraints.md new file mode 100644 index 0000000..d0f9135 --- /dev/null +++ b/docs/project-constraints.md @@ -0,0 +1,150 @@ +# Pebrel engineering contracts / 工程约束 + +These are project contracts, not claims that a numerical score proves good design. +The [evidence review](engineering-evidence.md) separates established practices from +local thresholds. See [architecture](architecture.md) for module responsibilities. + +## 1. File size: a safety limit, not a design score + +- Keep the existing **2000 physical-line hard limit**. Apply it to first-party + Rust and maintained `.py`, `.ps1`, `.mjs`, `.js`, `.sh`, `.lua` sources in the + declared roots. No maintained script exceeded this limit at adoption. +- **800 lines is advisory only**. Review cohesion and consider extraction; a + cohesive 801-line module is not automatically worse than fragmented wrappers. +- Physical lines include comments, tests and blanks; CRLF/LF and a final line + without a newline are handled consistently. Do not remove useful tests/comments, + compress formatting, or create `part1/part2` files to pass a size check. +- `architecture/file-budgets.txt` is the single shared source of roots, the hard + limit and legacy allowances. Eleven existing files exceeded 2000 at adoption. + They receive their measured size, not additional growth room. +- A normal PR cannot add/raise an allowance or raise the default limit. With + `--base`, an oversized file's permitted size is also bounded by its actual base + size, so an old allowance cannot be reused after the file has shrunk. +- Remove allowances when a file is deleted or reaches the default limit. A + reduction above that limit gives a tightening notice. No wildcard allowances. + +The Python checker runs offline and scans untracked local source additions too. +It fails on malformed budgets, missing roots, read errors and symlinked source +paths, including symlinked ancestors. It scans declared first-party roots only, +not repository-root probes, `tmp/`, release bundles or `third_party/`. A `target/` +directory is skipped only at a Cargo package/workspace root; a real `src/target/` +module remains covered. Dependency caches are not product sources. + +Generated translation tables live in Cargo output, not handwritten source roots. +JSON catalogs and other data assets use semantic/payload tests, not arbitrary +line-count limits. `nebula_app/tests/file_line_budget.rs` reads the same budget; +the Python PR checker additionally enforces history-relative ratcheting. + +## 2. Dependency direction + +`architecture/dependencies.toml` classifies every root workspace member and lists +allowed local dependencies separately for normal, build and test use. + +- Core crates must not depend on the application or acceptance lab. The policy + rejects direct renderer packages in core production/build dependencies. +- `nebula-settings`, `nebula-split` and `nebula_hook` retain their existing + zero-production-dependency contracts. Test-only tools are not prohibited by a + runtime-performance argument; they remain subject to normal dependency review. +- Normal/build local dependency edges must be acyclic, across the declared target + and optional configurations. Dev edges are checked for allowed direction but + do not create production cycles; the existing config/derive dev cycle is legal. +- Aliases resolve to their declared `package`; inherited workspace paths resolve + from the workspace root. Only resolved local paths form workspace graph edges. + An external older package with the same name is not silently treated as local. +- Every new workspace member needs a classification and source root. Workspace + globs/exclusions currently fail explicitly rather than silently escaping review. + Custom Rust target paths may be shared within declared roots, not outside them. + +This checker is not Cargo's resolver: it does not prove transitive third-party +dependency purity or analyze Rust macro/cfg-expanded intra-crate imports. Real +feature/platform builds remain required. In particular, `crate::display` is a +feature-selected shared facade in the GPUI product; a path-name blacklist would +be incorrect. Do not add such a blacklist without semantic evidence and fixtures. + +## 3. Responsibilities, interfaces and cost + +Required human review rules: + +- One authority for shared behavior: persistence, language registry, split rules, + terminal state and domain transitions must not be reimplemented per UI shell. +- Group by capability and lifecycle. Extract domain rules, I/O adapters, rendering + and tests where they have distinct responsibilities; do not require every tiny + feature to create all four files or another crate. +- Keep state private; expose the smallest useful command, query or result type. + Default to private or `pub(super)`; justify broader visibility. Avoid catch-all + `utils`, global service containers and traits with no concrete boundary need. +- Views must not block on network, disk scans, subprocess waits or long-held locks. + Async work needs ownership, cancellation, stale-result handling and cleanup. +- Hot-path changes require representative cost evidence. Static translation + lookup has a tested zero-allocation contract; formatting and cold-path I/O are + different operations. No universal ban on allocation or numeric timing gate. +- New UI text uses typed message IDs, named placeholders and explicit fallback. + The [i18n contract](internationalization.md) defines coverage and extension. +- Preserve compatibility identifiers and persisted semantics unless a separately + reviewed migration explicitly changes them. + +These judgments cannot be proven by line counts or a source regex. Reviewers must +ask whether an extraction reduces knowledge shared across modules, not just whether +it produces more files. + +## 4. Tests and rule changes + +Each new automated gate needs a stated invariant, a passing legitimate example, +a failing violation, and fixtures for known false positives. Guardrail bugs are +bugs: fix them before calling the gate mandatory. A failing architecture check must +not be ignored, but a demonstrably defective policy must be revisable. + +Record important changes in [the decision log](architecture-decisions.md): context, +evidence, alternatives, consequences, validation and a replacement/removal condition. +Ordinary fixes do not need ceremonial ADRs. A change to a budget or rule is a +dedicated governance change, not an unexplained edit hidden inside a feature PR. +No automatic exception-adding or budget-increasing command is provided. + +Emergency/security repairs must not be forced into a dangerous broad refactor just +to preserve a flawed metric. Escalate the demonstrated conflict to a maintainer, +record the scoped policy decision and its regression test, then repair the contract. +Do not silently disable the job or permanently widen unrelated allowances. + +Existing platform-cfg counting is a historical heuristic, not a proof of platform +decoupling. It is not promoted to this new gate: its comment/string/nesting behavior +needs separate work. Fork patches retain exact-revision pins, thin adapter scope, +recorded motivation and an upstream-removal condition. Release safety remains in +`AGENTS.md` and the existing verified release instructions. + +## Server-side activation + +The repository files alone do **not** activate GitHub merge protection. A maintainer +with the appropriate repository permissions must configure and verify: + +1. Require a PR and the unique **`architecture-contracts`** status check on protected + branches; require an up-to-date branch or an appropriately configured merge queue. +2. Require Code Owner approval. `@Kuddev` is the initial owner entry; verify the account + has write permission, and extend ownership to real maintainers as the team grows. + Before enabling this requirement, ensure another authorized owner can review a + maintainer-authored PR: an author cannot approve their own PR. With only one + maintainer, explicitly resolve and document this limitation and the emergency + process first; do not enable an unfulfillable approval requirement or invent an owner. +3. Dismiss stale approvals / require approval of the latest reviewable push. Protect + `CODEOWNERS` itself, workflows, checkers, budgets and decision records; the catch-all + owner entry covers these files as well as product source. +4. Apply rules to administrators and restrict bypass permissions according to the + repository's emergency process. A normal PR author must not waive their own gate. +5. Validate with a disposable PR: a known violation must fail and block merging; + the corrected PR must pass. Confirm review invalidation on a later policy edit. + +The workflow runs for every PR, including docs-only PRs, with no path filter and +without `continue-on-error`. It also accepts `merge_group` events. It uses read-only +permissions and ordinary `pull_request`, not privileged `pull_request_target` to +execute contributor code. The initial policy's base lacks a budget; only that +absence permits bootstrap. Empty/invalid budgets and unavailable base commits fail. + +Checkers and workflows are versioned code that a PR can change; required reviews +and server-side settings are the trust boundary. This change does not claim those +settings have already been enabled or that remote negative-PR tests have been run. + +## 中文要点 + +硬门禁只拦明确可测的合同:规模红线、存量不增长、清单依赖方向和独立编译/行为测试。 +800 行仅提示;模块职责、抽象是否值得、线程生命周期和热路径成本仍须人工评审。 +规范本身允许基于证据修正,不能靠“规则就是规则”维护错误设计,也不能借修规则绕过问题。 +服务端必需检查与 Code Owner 审批启用并实测后,才构成真正的合并约束。 diff --git a/docs/release-notes/unreleased.md b/docs/release-notes/unreleased.md index 0778a46..692e7c3 100644 --- a/docs/release-notes/unreleased.md +++ b/docs/release-notes/unreleased.md @@ -23,6 +23,8 @@ This file contains changes that are not part of a numbered release yet. - File-name indexing applies incremental updates and recovers from watcher queue overflow with a rescan; editing a file's contents alone no longer rebuilds its name entry. - Improved terminal formula parsing and rendering for streamed agent output, while preserving the original text when a formula cannot be rendered. - Added native platform adapters and preview packaging instructions for Linux and macOS. Native build, test and package validation remains a separate requirement before publishing those previews. +- Updated the public project and installation guides to use Pebrel consistently, while retaining the existing repository, command, configuration, and download identifiers. +- Added contribution, architecture, and translation guides with explicit compatibility and review requirements. GitHub branch protection still requires separate server-side setup and verification. ## 中文 @@ -45,6 +47,8 @@ This file contains changes that are not part of a numbered release yet. - 文件名索引采用增量更新,监听队列溢出时通过重新扫描恢复;仅编辑文件内容不再重建对应名称条目。 - 改进流式 Agent 输出中的终端公式解析与绘制,无法渲染时保留原始文本。 - 新增 Linux 和 macOS 原生平台适配及预览打包说明;发布这些预览前仍需单独完成原生构建、测试和打包验证。 +- 公开项目说明与安装指南统一采用 Pebrel 名称,同时保留现有仓库、命令、配置与下载标识。 +- 新增贡献、架构和翻译指南,明确兼容性与审查要求;GitHub 分支保护仍需单独在服务端配置并核验。 ## Contributors - [@Sakyvo](https://github.com/Sakyvo): terminal network proxy, conditional `Ctrl+C` copy, and word deletion with `Ctrl+Backspace` / 终端网络代理、`Ctrl+C` 按选区复制及 `Ctrl+Backspace` 按词删除。 diff --git a/scripts/tests/test_pebrel_branding.py b/scripts/tests/test_pebrel_branding.py index f81fb4e..f6768c2 100644 --- a/scripts/tests/test_pebrel_branding.py +++ b/scripts/tests/test_pebrel_branding.py @@ -76,15 +76,18 @@ class PebrelBrandingTests(unittest.TestCase): self.assertIn('.join("Nebula")', settings) self.assertNotIn('.join("Pebrel")', settings) - def test_preview_documents_compatibility(self): + def test_project_identity_without_local_preview_notice(self): changelog = self.source("CHANGELOG.md").split("## 1.5.0 -", 1)[0] self.assertIn("Pebrel", changelog) self.assertIn("not a new published release", changelog) self.assertIn("不代表新的已发布版本", changelog) readme = self.source("README.md") - self.assertIn("Pebrel is the new display name of Nebula Terminal", readme) - self.assertIn("not a new GitHub Release", readme) - self.assertIn("installer identity", readme) + self.assertIn('

Pebrel

', readme) + self.assertIn("Pebrel (formerly Nebula)", readme) + self.assertIn("https://github.com/Kuddev/nebula/releases", readme) + self.assertNotIn("Local branding preview", readme) + self.assertNotIn("本地品牌预览", readme) + self.assertNotIn("A name change does not create a new published release", readme) if __name__ == "__main__":