diff --git a/Furious/Actions/AGENTS.md b/Furious/Actions/AGENTS.md new file mode 100644 index 0000000..bb62d16 --- /dev/null +++ b/Furious/Actions/AGENTS.md @@ -0,0 +1,25 @@ +# Action guidance + +## Command boundary + +- Actions adapt one user command to presentation. Resolve live controller/repository state when triggered, delegate the + operation to its owner, and render the result; an action is not a second connection, routing, subscription, or + persistence authority. +- Prefer one shared `QAction` for one semantic command across menus and buttons so checked/enabled state, shortcut, + callback, and translation cannot diverge. A host widget may narrow shortcut context; do not make menu shortcuts + application-wide when focused editors or other controls own the same keys. +- Routing and connection actions render the shared controllers. Rebuilding a dynamic menu releases the old actions, + action group, and callbacks before publishing the new snapshot; user-defined labels remain untranslated. +- Existing import actions still combine capture/file/clipboard presentation with incremental repository insertion. Treat + that as a compatibility path, not a service template. Reuse plugin protocol parsing, construct a complete valid result + before each mutation, and keep batched GUI work cancellable and bounded per event-loop turn. + +## Lifetime, input, and verification + +- `AppQAction.callback` is a deliberate strong reference. The action owner must not outlive a captured receiver, and a + transient/repeated receiver uses the weak named-method facilities required by `Furious/Qt/AGENTS.md`. +- Clipboard text, files, QR images, share links, and plugin results are untrusted and may contain credentials. Bound + diagnostic excerpts and never log or echo a complete secret-bearing payload merely to explain a parse failure. +- Verify command state and delegation, cancellation/error presentation, shortcut scope in the real focused widget, menu + rebuild cleanup, and repeated dialog/capture/action lifetimes. When this command boundary changes intentionally, update + this guide and remove superseded compatibility wording in the same change. diff --git a/Furious/Backends/AGENTS.md b/Furious/Backends/AGENTS.md index 701c44c..d652570 100644 --- a/Furious/Backends/AGENTS.md +++ b/Furious/Backends/AGENTS.md @@ -25,22 +25,13 @@ - A runtime owns its exact process/thread/readers/monitors and publishes an actionable start error. Stop/dispose is bounded, idempotent, and correct after partial acquisition. -## Backend-specific invariants +## Backend scopes -- **Xray:** preserve the full JSON document, including unrelated inbounds/outbounds, routing, logging, extensions, and - unknown transport/security data. Tagged protocol/transport/TLS editors and URI codecs alter only their projection. - Compatibility transport-alias migration must be explicit. Xray also owns routing/assets/API statistics and its asset - environment contract; asset replacement is digest-verified and atomic. -- **Hysteria 1:** retain its legacy flat schema/share-link semantics and tolerated upstream values. Do not import - Hysteria 2 nested documents, obfuscation, statistics, or native-TUN policy. It uses application tun2socks when needed - and owns the MMDB/ACL assets consumed by its runtime. -- **Hysteria 2:** preserve the native nested client document, unknown future values, optional-group absence, and tagged - obfuscation siblings. Its runtime factory owns native-TUN privilege/address/route-exclusion policy and statistics - capabilities; registries retain descriptors/providers, not request-lifetime monitors/dialogs. -- **External Core:** model a user-selected executable, not a protocol binding. Validate absolute executable/working - directory, argument/environment types and NULs, endpoints, bounded shutdown timeout, and optional application-TUN - metadata before spawn. Execute an argument vector with `shell=False`; never log environment/arguments or search by - process name. The runtime owns one exact `Popen`, readers, watcher, buffering, termination escalation, and reaping. +- Read the selected backend's nested guide before changing its configuration, editor, protocol codec, runtime, TUN, + routing, asset, statistics, or process behavior. Those child guides own backend-specific compatibility details; keep + this parent focused on rules that every backend must satisfy. +- A shared backend-contract change must be checked against Xray, Hysteria 1, Hysteria 2, and External Core rather than + making the most feature-rich backend the implicit default for the others. ## Verification diff --git a/Furious/Backends/ExternalCore/AGENTS.md b/Furious/Backends/ExternalCore/AGENTS.md new file mode 100644 index 0000000..75ed86b --- /dev/null +++ b/Furious/Backends/ExternalCore/AGENTS.md @@ -0,0 +1,24 @@ +# External Core guidance + +## Structured executable boundary + +- External Core represents one user-selected local executable, not an embedded protocol binding. Keep executable path, + optional working directory, argument vector, environment overrides, HTTP/SOCKS endpoints, shutdown timeout, remote + TUN address, and application-tun2socks opt-in distinct while preserving unknown top-level fields. +- Loading is observational: do not silently absolutize or rewrite relative paths. Validation before spawn owns path + existence/type, argument and environment types/NULs, endpoint requirements, and a finite bounded shutdown timeout. +- Execute an argument vector with `shell=False`. Never concatenate a shell command, search or kill by process name, or + log arguments/environment values that may contain credentials. + +## Runtime and TUN ownership + +- One runtime owns its exact `Popen`, stdout/stderr pipes and readers, watcher, partial-line buffer, exit callback, and + reaping path. Shutdown terminates that process, uses only platform-specific escalation for its PID when necessary, + kills as a last resort, joins readers, and remains bounded and idempotent after partial startup. +- Application tun2socks is an explicit profile capability. It requires a usable SOCKS endpoint and a separate remote + server address for bypass routing; an executable path is never a network destination, and this backend never invents + native core TUN support. Subscription decoding must continue to reject executable profiles. +- Verify unknown-field and editor round trips, path/argument/environment validation, paths with spaces, immediate-exit + failure, complete and partial output, exact callback/reader/watcher cleanup, repeated stop/dispose, TUN opt-in and + remote-address handling, subscription rejection, and transient editor destruction. Update this guide when the process + contract evolves rather than preserving today’s implementation mechanically. diff --git a/Furious/Backends/Hysteria1/AGENTS.md b/Furious/Backends/Hysteria1/AGENTS.md new file mode 100644 index 0000000..7aff971 --- /dev/null +++ b/Furious/Backends/Hysteria1/AGENTS.md @@ -0,0 +1,15 @@ +# Hysteria 1 guidance + +- Hysteria 1 is the legacy flat client schema and `hysteria://` share-link backend. Do not import Hysteria 2 nested + documents, obfuscation, statistics, realm, or native-TUN semantics merely because the upstream names are related. +- Preserve tolerated legacy types, upstream field names, absent defaults, and unknown combo values. Loading and an + untouched editor/URI/mapping round trip are observational; explicit user edits may normalize only the represented + field. +- Subscription import is allowed only through supported Hysteria 1 protocol handlers. Subscription identity and test + metadata stay in `ServerProfile`, and validation diagnostics never disclose passwords or complete links. +- Runtime and download-test preparation use independent configuration copies. This backend uses application tun2socks + when global TUN requires it and owns the MMDB/ACL inputs used by its routing launch; it does not gain native TUN by + falling through another backend’s policy. +- Verify legacy/current URI and mapping compatibility, unknown/tolerated values, stored-copy isolation, MMDB/ACL + absence or malformed paths, asynchronous readiness and rollback, core-exit translation, application-TUN policy, and + repeated editor/runtime cleanup. Revise this guide with an intentional schema evolution instead of freezing quirks. diff --git a/Furious/Backends/Hysteria2/AGENTS.md b/Furious/Backends/Hysteria2/AGENTS.md new file mode 100644 index 0000000..f881cdb --- /dev/null +++ b/Furious/Backends/Hysteria2/AGENTS.md @@ -0,0 +1,23 @@ +# Hysteria 2 guidance + +## Native document and editor projection + +- The persisted Hysteria 2 client document is authoritative and is submitted to the embedded runtime. The GUI is a + partial projection, not an Xray-shaped compiler or a general upstream-schema normalizer. +- Preserve upstream names, optional-group absence, unknown siblings, and future string values. Effective defaults such + as `realm.ipMode` are presented without materializing them during an untouched save; editing one leaf changes only + that leaf. +- `obfs.type` selects tagged subtype data. Unknown types remain visible and survive untouched. An explicit switch to a + known type may remove incompatible subtype branches, but never unrelated document branches. + +## TUN, statistics, and lifecycle + +- Managed native TUN replaces only the runtime copy’s `tun`. Disabled management preserves any explicit `tun`, including + malformed data for the core to reject; only absence permits application tun2socks. Linux native TUN requires the + backend’s privilege and server-route-exclusion guarantees. Probe/download copies always remove native TUN. +- Traffic-statistics targets, setting descriptors, and action providers are process-lifetime plugin capabilities; + monitors, replies, dialogs, and runtimes created from them are request/transient objects and are never registry-owned. +- Verify nested sibling/default preservation, known and unknown values, obfuscation switching, URI/document equality, + every native/application-TUN and resolution case, probe stripping, readiness/exit cleanup, statistics cancellation, + and repeated transient editor/settings-dialog destruction. Keep this guide synchronized with verified upstream schema + changes rather than treating current field lists as permanent. diff --git a/Furious/Backends/Xray/AGENTS.md b/Furious/Backends/Xray/AGENTS.md new file mode 100644 index 0000000..10297d4 --- /dev/null +++ b/Furious/Backends/Xray/AGENTS.md @@ -0,0 +1,25 @@ +# Xray guidance + +## Full-document preservation + +- The complete Xray JSON document is authoritative. Protocol, transport, TLS, local-endpoint, logging, routing, and TUN + editors are partial projections; preserve unrelated inbounds/outbounds, extensions, unknown security/transport data, + and unrepresented siblings. +- Loading is observational except for narrow tested compatibility migrations. Legacy transport aliases such as `http`, + `gun`, and `mkcp` may map to their supported current representation, but do not expand this into general normalization + of unknown future values. +- URI codecs round-trip only their supported projection without erasing the source document. Keep Shadowsocks plugin + metadata and SOCKS/VMess/VLESS/Trojan semantics distinct; malformed input returns controlled validation rather than a + plausible different profile. + +## Runtime-specific capabilities + +- Logging paths, selected routing, statistics API, local test endpoints, and TUN are prepared on an independent runtime + copy. Managed native TUN replaces runtime TUN inbounds; disabled management preserves explicit valid or malformed TUN + and suppresses tun2socks. Proxy/download tests replace inbounds with their proxy-only test surface. +- Xray owns routing profiles/options, geo assets, API statistics, and the `XRAY_LOCATION_ASSET` environment contract. + Asset replacement remains digest-verified and atomic; action providers retain reusable routing/asset windows only + through the created action owner and create transient settings dialogs per request. +- Verify full-document and URI preservation, aliases and unknown values, runtime-copy isolation for routing/log/TUN/tests, + multiple TUN inbounds, asset integrity/failure, statistics and process cleanup, compiled-safe UI callbacks, and + repeated editor/window destruction. Update this scope when an upstream or plugin capability changes intentionally. diff --git a/Furious/Controllers/AGENTS.md b/Furious/Controllers/AGENTS.md new file mode 100644 index 0000000..092305c --- /dev/null +++ b/Furious/Controllers/AGENTS.md @@ -0,0 +1,25 @@ +# Controller guidance + +## Shared state authorities + +- Controllers own process-lifetime shared state and transition policy. They coordinate injected repositories/services + and publish structured Qt signals; they do not own transient widgets, network replies, core processes, or worker pools. +- `ConnectionController` is the sole connection state machine. A GUI start remains `Connecting` while one generation- + checked `ConnectionManager` transaction acquires readiness/TUN resources; System Proxy and the active-profile commit + occur only after success. Disconnect/reconnect cancels the exact in-flight generation and ignores stale completion. +- Preserve state and signal ordering, interaction gating, the exact selected `ServerProfile`, runtime snapshots, + reconnect preference, and rollback after validation, runtime, TUN, System Proxy, cancellation, or unexpected-exit + failure. Worker/native callbacks cross to the controller’s Qt thread before transition. +- `RoutingController` owns available capability options plus selected/persisted routing. Distinguish a newly selected + repository profile from the profile snapshot already owned by a live connection; changes use controlled reconnect, + not mutation of the running document. User-defined routing labels are semantic data, not translatable UI literals. +- `SettingsController` is the shared policy path used by Home, Settings, tray, and platform integration. Validate + availability and complete host effects before persisting success; UI surfaces render its signals rather than keeping + duplicate preference state. + +## Verification and evolution + +- Test exact states and signal counts for async success, invalid input, supersession, cancellation, partial acquisition, + System Proxy failure, unexpected exit, routing refresh/reconnect, startup restoration, failed host settings, missing + partial-startup dependencies, and repeated shutdown. If ownership moves deliberately, update this guide and the + affected controller tests instead of keeping a compatibility controller as a second authority. diff --git a/Furious/Extensions/AGENTS.md b/Furious/Extensions/AGENTS.md new file mode 100644 index 0000000..c2aa2a0 --- /dev/null +++ b/Furious/Extensions/AGENTS.md @@ -0,0 +1,15 @@ +# Bundled extension guidance + +- `Extensions` contains host-shipped plugins that are not proxy runtimes. They register through the same public API and + lifecycle as entry-point plugins and receive no private repository, controller, or UI side channel. +- `StandardSubscriptionPlugin` owns format recognition and decoding only. A decoder returns an immutable neutral + `SubscriptionResult`; profile construction/metadata belongs to `SubscriptionImportService`, and group reconciliation, + request generations, timers, persistence, and post-commit effects belong to the subscription service/repository path. +- Decoder probing is priority-ordered and failure-isolated. Return `None` when a format does not match, validate the + declared result shape, preserve useful names/upstream IDs, and never log a complete payload or link. Current standard + formats are linear plain/Base64 share-link envelopes; introduce explicit size/depth/work limits before adding richer + recursive or nested formats. +- Keep bundled registration deterministic, side-effect-light, and discoverable in source, wheel, and Nuitka builds. + Test format selection/fallback, malformed and secret-bearing input, duplicate occurrence identity, unsupported + subscription protocols, registration rollback, and absence of repository/UI mutation during decoding. Evolve this + guide with the decoder contract rather than giving bundled formats permanent special treatment. diff --git a/Furious/Interface/AGENTS.md b/Furious/Interface/AGENTS.md new file mode 100644 index 0000000..e64f7cc --- /dev/null +++ b/Furious/Interface/AGENTS.md @@ -0,0 +1,19 @@ +# Interface guidance + +- This package defines dependency-light contracts shared across layers. It does not import Qt presentation, + controllers, services, repositories, plugins, or concrete backends; a contract may depend on a small model/constant + only when that does not trigger application construction or registration. +- Contracts specify observable ownership, lifecycle, mutation, serialization, callback, and failure semantics. Search + every representative implementation and contract test before changing one; an implementation may strengthen a + guarantee but cannot silently weaken it. +- `CoreRuntime` is mechanism-neutral: embedded multiprocessing, direct `subprocess`, or an in-process binding can satisfy + it. Preserve actionable `startError()`, callback/exit behavior, runtime identity, serialization diagnostics, and a + bounded idempotent stop/dispose path. Process/child terminology belongs only to implementations that own one. +- `StorageBackend.data()` deliberately exposes a live mutable collection for compatibility. Do not reinterpret it as a + snapshot or introduce a second authoritative cache. Editor bindings map input to configuration and back; they do not + decide runtime, persistence, or host policy. +- `ApplicationRunner.ExitCode` is a process-boundary protocol. Shared encoders and non-throwing configuration + construction preserve their distinct diagnostics so callers do not collapse every empty result into the same error. +- Verify cheap/import-independent contracts plus representative runtime, storage, editor, application-exit, encoding, + and configuration implementations. Update this guide when a contract intentionally changes, together with all + implementers and compatibility tests. diff --git a/Furious/Models/AGENTS.md b/Furious/Models/AGENTS.md new file mode 100644 index 0000000..d4ace15 --- /dev/null +++ b/Furious/Models/AGENTS.md @@ -0,0 +1,25 @@ +# Model guidance + +## Domain shape and identity + +- Models are core-neutral Python data and transformations. Do not import Qt, globals, repositories, services, + controllers, plugin registries, or concrete backends into this layer. +- `CoreConfiguration` is a dict-like connection document whose construction is deliberately non-throwing: unsupported + or malformed input becomes an empty object with `constructionError()`. Keep construction and serialization errors + distinct and preserve useful context through callers. +- `ServerProfile` composes an independent connection document with `ProfileMetadata`. Display name, stable profile ID, + subscription ownership/key, latency, speed, annotations, and local flags never become core-configuration fields. +- Preserve unknown metadata and legacy aliases across load/save. `independentCopy()` creates a manual profile with a new + ID and no subscription owner; a runtime `deepcopy()` preserves identity while isolating mutable preparation. +- `ensureProfile()` normalizes rather than clones: metadata arguments update an existing profile. Use an independent + copy for a new stored item and a runtime copy when logical identity must survive without mutating persistence. +- Profile ID, object identity, subscription source/key, connection fingerprint, display text, and row position answer + different questions. Fingerprints require deterministic JSON-compatible connection data and fail explicitly. + +## Compatibility and verification + +- Protocol construction/export belongs to plugin capabilities. Compatibility shims may remain while callers migrate, + but new protocol-name branches do not belong in core models. +- Verify malformed/current/legacy/unknown-field round trips, metadata/connection separation, copy/identity semantics, + deterministic fingerprints, construction/serialization diagnostics, and capability-based import/export. Revise this + guide with intentional domain changes; do not preserve a legacy identity rule after migration replaces it. diff --git a/Furious/Utility/AGENTS.md b/Furious/Utility/AGENTS.md new file mode 100644 index 0000000..46fc1ae --- /dev/null +++ b/Furious/Utility/AGENTS.md @@ -0,0 +1,15 @@ +# Outer process guidance + +- `Utility` owns the child-side wrapper used by the outer application process and crash/exit translation. It is not a + miscellaneous helper namespace and does not own application composition, repositories, runtimes, or UI policy. +- `AppMainProcess` owns one exact Qt application child and one small synchronized crash-log result. Do not add a + `multiprocessing.Manager` or auxiliary child merely to communicate status, and preserve the platform’s explicit spawn + behavior. +- Exception and signal handling must work before and after application construction. Preserve semantic + `ApplicationRunner.ExitCode` values, original exception/traceback context, and best-effort crash logging; a log-write + failure never replaces the primary failure. +- The parent entry point joins only the child it created and shows the fallback Qt report only for a nonzero result. + Never discover or terminate processes by name, and keep normal/source/packaged command-line entry points equivalent. +- Verify normal return, exception, assertion, signal, pre-application failure, crash-log failure, command dispatch, + cross-platform spawn, exact child joining, and absence of manager servers or orphaned resources. If this process + topology changes intentionally, rewrite this guide rather than layering another supervisor over the old one. diff --git a/Furious/Widget/AGENTS.md b/Furious/Widget/AGENTS.md new file mode 100644 index 0000000..bf3feb9 --- /dev/null +++ b/Furious/Widget/AGENTS.md @@ -0,0 +1,28 @@ +# Reusable widget guidance + +## Presentation and identity + +- Widgets present state below pages/windows. Prefer explicit controller/service/repository inputs and do not add new + application-global reach-through or a duplicate state cache; existing global access is compatibility debt, not a + template. +- Table/list models wrap live repository collections. Bracket mutations with correct begin/end or layout notifications, + keep index/deleted compatibility fields synchronized, and map proxy indexes to source objects before acting. Stable + profile/subscription IDs—not display text, object row, or current sort order—preserve selection, focus, activation, and + async write-back. +- Sorting/filtering/reordering must retain logical selection and keyboard focus. Recursively scope table-owned menu + shortcuts as `WidgetShortcut` so a focused editor or another surface keeps its own shortcut semantics. + +## Workflow and lifetime boundaries + +- The server and subscription views share one subscription workflow owner. Subscription UI issues commands and renders + sync state; it does not duplicate download, decode, reconciliation, timer, persistence, or post-commit behavior. +- `ServerTableView` owns selection and cell repaint for profile tests, while `ProfileTestManager` owns scheduling, + concurrency, temporary runtimes, cancellation, stable-target validation, and latency/speed mutation. Repository or + subscription changes are forwarded as invalidation boundaries; stale results never write by row. +- Models, delegates, headers, menus, actions, animations, spinners, WebEngine/map objects, timers, workers, and replies + each need one owner. Persistent widgets connect once and refresh state; visibility may pause rendering/animation, not + application-level log draining, traffic collection, or other service ownership. +- Verify sorted/filtered commands, notification ranges, identity-preserving move/delete, real keyboard focus and nested + shortcuts, subscription/test cancellation, hidden-page rendering, exact cell updates, optional WebEngine fallback, + and repeated cleanup to baseline. Update this guide when ownership moves; never move service orchestration back into + a widget just to preserve historical wording. diff --git a/Furious/Window/AGENTS.md b/Furious/Window/AGENTS.md new file mode 100644 index 0000000..0181e51 --- /dev/null +++ b/Furious/Window/AGENTS.md @@ -0,0 +1,33 @@ +# Window and page guidance + +## Composition and shared state + +- `MainWindow` owns the persistent built-in page tree and navigation; plugin pages enter through the plugin navigation + service. Pages adapt shared controllers/services/repositories and must not become competing state authorities. + Preserve application-facing forwarding APIs until their consumers migrate deliberately. +- Home, Settings, tray actions, and reusable dialogs render the same connection, routing, and settings controllers. + Platform/capability availability affects presentation but does not authorize an unsupported persisted value or a + duplicate host side effect. +- The current page composition shares one subscription workflow between server and subscription presentation, records + traffic into one history, and derives metrics/endpoint presentation from owned services. These exact locations may + evolve, but a refactor retains one durable owner, one scheduler/request path, and one signal path. +- Home remains the initial page and navigation expansion/selection is session-local unless a product decision adds a + persisted migration. Plugin ordering and bottom settings placement remain declarative navigation concerns. + +## Visibility, lifetime, and geometry + +- Long-lived pages construct persistent controls, models, timers, services, and connections once. Page visibility may + coalesce log/graph painting or deliberately gate a lazy endpoint lookup, but it never owns log collection/draining, + traffic sampling, subscription schedules, or an already-started request. +- One-shot editors/prompts use managed transient dialogs and weak compiled-safe continuations. Reusable windows such as + the text editor and parent-owned settings dialogs retain one explicit owner, reset on reopen, and use normal close + semantics; do not convert every top-level surface to delete-on-close or global retention. +- Use normal layouts and `AppQ*` controls. Restore top-level geometry only after persistent composition and through the + canonical first-show path; never-shown Qt fallback geometry must not overwrite a prior user decision. + +## Verification and evolution + +- Verify initial/plugin navigation, shared Home/Settings/tray state, service ownership, lazy rendering versus continuous + collection, async continuation cleanup, unsaved-close behavior, translation/theme changes, geometry migration, and + repeated open/show/hide/destroy stability with real Qt input where semantics depend on it. Keep this guide as current + architectural memory: change it with intentional page ownership, not after forcing new code through stale structure.