Move the pending activity, input and SSH authentication decisions into their module-owned notes under the current governance contract. Import the shutdown draft type directly after the incoming drag-preview cleanup removes its parent import.
106 lines
7.0 KiB
Markdown
106 lines
7.0 KiB
Markdown
# 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/ai_hook` | Normalized provider facts, bounded ordering, one shared pane lifecycle and owned installation policy; Windows adapters | Screen keyword rules or a separate state machine per UI shell |
|
|
| `nebula_app/src/platform/ssh_agent.rs` | Native agent endpoints, transport connection and bounded identity discovery | Host authentication policy or private key selection |
|
|
| `nebula_app/src/ssh_session/agent.rs` | SSH agent identity selection, signing outcomes and total discovery budget; fresh scope per host | A second authentication plan, credential store or agent forwarding service |
|
|
| `nebula_app/src/ssh_session/integration.rs` | Authenticated exec/PTY orchestration for remote hook installation and shell startup | Provider policy or a second Agent state machine |
|
|
| `nebula_app/src/ai_agents` | Agent identity and structurally constrained screen observations | Authority to overwrite hook results or infer remote completion from silence |
|
|
| `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),
|
|
the [causal note policy](../architecture/notes/AGENTS.md), and the
|
|
[legacy decision archive](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。
|
|
拆文件必须减少跨模块知识,不以文件数增加作为解耦证明;旧大文件按相关功能逐步治理。
|