Refine repository agent guidance

Signed-off-by: Loren Eteval <loren.eteval@proton.me>
This commit is contained in:
Loren Eteval
2026-08-21 13:26:56 +08:00
parent 585c5f75c3
commit cbf759667b
4 changed files with 22 additions and 15 deletions
+13 -8
View File
@@ -9,15 +9,17 @@
- Before Python work, inspect the repository root for `.venv*` or `venv*` and prefer its interpreter when usable. Do not
create or modify an environment unless required.
- Keep edits focused. Preserve GPL headers, `from __future__` placement, import grouping, repository naming style, and
public compatibility unless a deliberate migration is part of the task.
public compatibility unless a deliberate migration is part of the task. Treat curated package `__init__` exports,
plugin API dataclasses, persisted keys, and semantic exit codes as compatibility surfaces.
## Pythonic design
- Prefer the simplest design that makes ownership, state transitions, failure, and side effects explicit. Readability
and one canonical path beat clever indirection or parallel implementations.
- Keep policy close to the layer that owns it: models describe data, repositories persist domain collections,
`AppSettings` persists preferences, services perform workflows, controllers own shared runtime state/orchestration,
plugins/backends own protocol-specific behavior, and UI adapts those APIs.
`AppSettings` persists preferences, services own workflows and temporary resources, controllers own shared state
machines/orchestration, plugins/backends own protocol-specific behavior, `Application` composes the process, and UI
adapts those APIs.
- Make invalid states and boundary failures visible with specific return values, result objects, or exceptions. Catch
broadly only at a genuine isolation boundary, log actionable context, and do not silently convert explicit user input
into a different behavior.
@@ -32,11 +34,12 @@
- Treat persisted user configuration as input. Connection, routing, testing, logging, TUN, and statistics preparation
must not mutate it implicitly; use explicit runtime/derived state unless an API is documented as mutating storage.
- Prefer plugin capabilities/factories over protocol or core conditionals in shared managers. Registries store classes,
factories, descriptors, and immutable metadata—not transient UI instances.
- `CoreRuntime` means one managed proxy-core lifecycle regardless of whether its implementation uses a subprocess,
multiprocessing, or an in-process binding. Reserve process terminology for actual operating-system processes and
handles.
- Prefer plugin capabilities/factories over protocol or core conditionals in shared managers. Registries may strongly
own process-lifetime plugins, capability providers, factories, descriptors, and metadata; they must not retain
transient UI or active runtime instances.
- A `ServerProfile` combines profile metadata with one persisted connection/configuration document. `CoreRuntime` means
one managed proxy-core lifecycle regardless of whether its implementation uses a subprocess, multiprocessing, or an
in-process binding. Reserve process terminology for actual operating-system processes and handles.
- Application-wide controllers and repositories may be process-lifetime. Transient UI, network replies, timers,
callbacks, and temporary processes must not become accidental global state.
- Keep platform mutation behind `Frozenlib`/runtime abstractions so unsupported platforms remain safe to import and
@@ -54,6 +57,8 @@
specifications, and `.format(...)` inside `_()` are unsupported.
- Curly braces in extracted strings are reserved for application-constant substitution, not ordinary runtime
placeholders.
- Keep both source execution and the `Deploy.py`/Nuitka build viable. Plugin discovery and optional heavy imports must
remain statically discoverable or explicitly included without introducing import-time application/UI construction.
## Verification and review
+3 -4
View File
@@ -2,10 +2,9 @@
## Layering and state
- `Models` and `Interface` define core-neutral data and contracts. `Repository` owns persisted domain collections,
`AppSettings` owns preferences, `Service` owns workflows/resources, `Controllers` own shared runtime state,
`Plugins`/`Backends` own protocol behavior, and `Application` composes them. `Qt`, `Widget`, and `Window` present that
state.
- `Application` is the deliberate broad composition layer. Elsewhere, depend on the narrowest lower-level contract and
avoid circular imports or reaching through a page/window when a controller, service, repository, or plugin capability
owns the operation.
- Existing UI code has compatibility paths that reach repositories or application globals. Do not extend that coupling
when a controller/service API can be introduced cleanly; migrate incrementally rather than creating a second state
authority.
+3 -3
View File
@@ -1,8 +1,8 @@
# Application composition guidance
- `DesktopApplication` is the composition root. It creates or acquires and durably owns application-lifetime
controllers, repository access, services, pages, main window, tray, thread pool, singleton IPC endpoint, and plugin
registry integration.
- `DesktopApplication` is the composition root. It durably owns process-lifetime controllers, logging, the main window,
tray, thread pool, singleton IPC endpoint, cleanup stack, and plugin-registry lifecycle. `MainWindow` owns the built-in
page/widget tree and page-level managers through normal Qt parentage; do not duplicate those owners in the application.
- Keep bootstrap order explicit: environment/plugins and storage before consumers, controllers/services before UI, and
restoration only after all dependencies exist. Accessors must tolerate partial startup and cleanup.
- Each successful startup stage registers its exact cleanup immediately. Partial startup and final shutdown use the
+3
View File
@@ -6,6 +6,9 @@
dispatch, statistics providers, and tests.
- Plugins contribute factories, handlers, descriptors, immutable metadata, and service providers—not live transient
widgets, active core instances, or controller state.
- The registry intentionally keeps registered plugin and capability-provider objects strongly reachable for the
registry lifetime. Their initialization/shutdown contract must release any resources they acquire; this ownership is
not permission to cache factory-created UI or runtimes.
- Protocol parse/export/editor, backend runtime, routing/TUN, statistics, subscription decoding, and navigation behavior
belongs behind capabilities. Shared code must not add core-name conditionals when capability dispatch can express the
policy.