mirror of
https://github.com/LorenEteval/Furious.git
synced 2026-10-09 15:19:56 +03:00
7.1 KiB
7.1 KiB
Furious package guidance
Inherit the nearest parent guide.
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
Applicationis 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 inRepository; temporary work/external resources inService; shared transitions inControllers; backend variation in plugin contracts/implementations; host mutation inFrozenlibor a runtime; presentation inQt,Widget,Window, orActions. InterfaceandModelsstay 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__.pyfiles 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
ServerProfilekeeps 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.mdeven fromWidget,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.pyandtests/test_plugin_architecture.pyare starting points for import/export boundaries; consult the relevant behavior module intests/README.mdas well. Update this boundary map when ownership changes, without turning the present import graph into a ban on deliberate refactoring.