mirror of
https://github.com/LorenEteval/Furious.git
synced 2026-10-10 16:28:24 +03:00
83 lines
7.1 KiB
Markdown
83 lines
7.1 KiB
Markdown
# Furious package guidance
|
|
|
|
Inherit the [nearest parent guide](../AGENTS.md).
|
|
Package exports expose contracts without transferring state or resource ownership. Domain, persistence,
|
|
workflow and presentation boundaries remain separate.
|
|
Read `Furious/__init__.py` with `tests/test_public_api.py`; paths are relative to this source tree's root.
|
|
|
|
## Responsibility boundaries
|
|
|
|
- `Application` is the composition root. Elsewhere depend on the narrowest model, repository, service, controller, or
|
|
plugin capability that owns the decision; do not add a second cache or state path to avoid an existing boundary.
|
|
- Domain shape, identity, and pure configuration transformations belong in `Models`; restoration, migration, ordering, and
|
|
durable mutation in `Repository`; temporary work/external resources in `Service`; shared transitions in
|
|
`Controllers`; backend variation in plugin contracts/implementations; host mutation in `Frozenlib` or a runtime;
|
|
presentation in `Qt`, `Widget`, `Window`, or `Actions`.
|
|
- `Interface` and `Models` stay dependency-light and must not import UI, controllers, services, repositories, or concrete
|
|
backends. Backend/runtime modules remain importable without constructing editors or the application.
|
|
- Package `__init__.py` files are curated compatibility surfaces, not mirrors. Import-time settings registration and
|
|
lazy capability imports are distinct from application construction or plugin discovery. Preserve that distinction
|
|
when changing exports; trace transitive imports and public-import/packaging tests, not just the edited module.
|
|
Wildcard exports can force lazy attributes to load, so check ordinary, wildcard, and cold-process imports
|
|
separately. Importability means preserving the actual side-effect boundary, not merely avoiding a syntax error.
|
|
Python export aliases, distribution names, native-module names, and persisted identifiers serve different consumers;
|
|
inspect each affected surface before renaming one. An import alias does not migrate stored data or transfer ownership.
|
|
|
|
## State, data, and ownership
|
|
|
|
- A `ServerProfile` keeps connection data separate from metadata such as display name, stable profile ID, subscription
|
|
ownership, latency, and speed. Independent stored copies get new identity; runtime copies preserve identity while
|
|
isolating mutable connection preparation.
|
|
- Keep identity checks at the boundary that can still reject the operation: the repository for stored identity,
|
|
the workflow for request freshness, and the presenter for current model mapping. A valid profile ID does not
|
|
authorize an old callback to mutate a replacement operation. Models defines the individual identity/copy contracts.
|
|
- Repository collections are live compatibility views owned once by `Storage`; do not wrap them in a competing
|
|
authoritative collection. Prefer named repository mutations for new behavior so validation and commit points remain
|
|
explicit.
|
|
- Process-lifetime global accessors expose deliberate application owners and can be unavailable during partial startup,
|
|
isolated tests, or teardown. New code prefers explicit dependencies; compatibility callers tolerate absence rather
|
|
than inventing fallback globals.
|
|
- UI/lifetime work consults `Furious/Qt/AGENTS.md` even from `Widget`, `Window`, `Actions`, or a backend; that sibling
|
|
scope owns the shared presentation contract. A forwarding attribute or global accessor exposes an existing owner,
|
|
not permission to construct a replacement service when the owner is absent.
|
|
|
|
## Change routing
|
|
|
|
- Controllers publish shared state and coordinate resource-owning services. New service APIs publish outcomes for UI
|
|
consumers rather than create presentation. Existing update-service dialogs and settings/controller prompts are
|
|
compatibility paths, not evidence of a strict UI-free service/controller layer; preserve callers until
|
|
deliberately separating those responsibilities. Some shared managers are currently constructed under persistent
|
|
widgets/pages. Construction location does not transfer workflow authority to every view: moving an owner must
|
|
preserve one scheduler, result boundary, and cleanup path. Widgets should not absorb new workflow orchestration.
|
|
- Plugin registries index process-lifetime plugins, descriptors, and capabilities. Created editors and active
|
|
runtimes transfer to explicit UI/workflow owners. A capability may own a reusable service, such as asset updating,
|
|
but that service still needs a cleanup boundary. Capability dispatch does not implicitly clone input or commit
|
|
preferences: callers establish isolation and the owning controller/repository establishes mutation. Built-ins use
|
|
the public capability contract; existing global-access helpers are host integration, not an extra requirement
|
|
for external plugins.
|
|
- Keep GUI work bounded, cross worker results through the owning Qt thread, and define cancellation/supersession for
|
|
every asynchronous workflow. Page visibility may control rendering, never ownership of collection or draining.
|
|
- Preserve unknown/forward-compatible fields through model, repository, backend editor, and serialization changes.
|
|
Apply that rule to open profile/core documents; closed application-owned option schemas reject unsupported fields.
|
|
Compatibility normalization must be narrow, intentional, and tested separately from observational loading.
|
|
Choose the representation required by the next boundary: profile for identity/metadata, connection document for
|
|
backend preparation, repository record for persistence. Consult Models/Repository for their copying and encoding
|
|
contracts; converting between these representations does not itself validate, isolate, or commit data.
|
|
- Application TUN configuration is not a proxy-core protocol or part of a stored server's connection document.
|
|
Do not add engine identifiers/options to protocol dispatch merely to reach host orchestration. Keep closed
|
|
customization schemas separate from open backend documents and from profile identity/metadata.
|
|
- Import, clipboard, share-link, file, and QR paths reuse the owning plugin codecs and validation. QR is a presentation
|
|
transport, not a second protocol parser. Decoding a transport envelope, validating a protocol, and committing a
|
|
profile are separate boundaries: a recognized envelope is not permission to clear a group or import an unsupported
|
|
protocol. Construct a complete valid result for each commit unit and never log the secret-bearing payload.
|
|
|
|
## Local guides
|
|
|
|
- Read the applicable specialized guide for application composition, embedded core processes, platform helpers,
|
|
repositories, plugins, services, backends, Qt ownership, translations, or bundled data. A missing child guide means
|
|
this file and the root guide are sufficient; do not recreate one merely to restate them. Existing child guides are
|
|
established scopes: clarify inheritance or local invariants rather than deleting or consolidating them.
|
|
- `tests/test_public_api.py` and `tests/test_plugin_architecture.py` are starting points for import/export
|
|
boundaries; consult the relevant behavior module in `tests/README.md` as well. Update this boundary map when
|
|
ownership changes, without turning the present import graph into a ban on deliberate refactoring.
|