diff --git a/.github/AGENTS.md b/.github/AGENTS.md index af7fdee..e3b1af9 100644 --- a/.github/AGENTS.md +++ b/.github/AGENTS.md @@ -1,5 +1,8 @@ # Release workflow guidance +Inherit repository-wide rules from the root `AGENTS.md`. This scope owns build/publication evidence and target-specific +exceptions; it does not define the source test suite or imply that every package dependency is pinned. + ## Publication and matrix contract - `workflows/deploy-pypi.yml` is both packaging coverage and the publication graph. Pull requests and ordinary pushes @@ -30,3 +33,8 @@ - Validate YAML and every affected expression/shell. Trace each changed matrix row through dependency installation, source/native import checks, Nuitka/installer output, packaged architecture/dependency checks, artifact upload, and tag gates. When a target cannot run locally, add a narrow CI assertion that fails before publication with a useful reason. +- The current workflow performs packaging/import/native checks but does not run the unittest behavioral suite. Do + not call an artifact build a regression-test pass; use `tests/README.md` for source verification. Check actual + `needs` and tag gates rather than assuming a downstream publish job runs on every build. +- Revalidate version/architecture claims against the current matrix instead of duplicating all pins here. When build + topology intentionally changes, update this scope and follow every consumer through upload and publication. diff --git a/AGENTS.md b/AGENTS.md index e49f478..17f6643 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -22,6 +22,11 @@ - Add a new AGENTS file only when verified architecture has a durable uncovered scope that no existing file can represent. A new scope never makes an existing one disposable. Keep override files explicit about which inherited assumption they replace and why. +- Before a hierarchy-wide audit, inventory tracked, untracked, hidden, and ignored AGENTS paths, including + overrides; record each scope and its nearest ancestor guide. At handoff compare exact path sets and Git + status/diff: no original path may disappear or become a rename. Default to exact equality and improve redundant + scopes in place. +- Inheritance follows directory ancestry. A sibling guide identifies a contract to consult, not another parent. ## Operating model @@ -46,11 +51,16 @@ post-commit side effect is reported without pretending the commit rolled back. - Use stable domain identity, not table rows, proxy indexes, display text, or object position. Async results additionally prove that the target generation/fingerprint is still current before mutation. +- Distinguish profile identity, subscription membership, remote synchronization ownership, and execution snapshots. + Moving a profile into a group does not transfer remote ownership; a running core uses its prepared document even + when the live profile later changes. - Startup and other staged workflows own every resource acquired before commit and roll back only that attempt on failure, cancellation, or supersession. Cleanup is bounded where responsiveness requires it, idempotent, and targets exact processes, threads, replies, timers, files, handles, routes, and callbacks—never process names. -- Keep GUI-thread work bounded. Blocking host/process/network work runs behind an owned worker or asynchronous Qt - boundary; workers publish data back to the owning Qt thread and never mutate widgets or live repositories directly. +- Keep new GUI-thread work bounded through an owned worker or asynchronous Qt boundary; workers publish data back to + the owning Qt thread and never mutate widgets or live repositories directly. Existing synchronous compatibility + and host-operation paths require explicit responsiveness review: an async entry point alone does not prove + non-blocking preparation, cancellation, or shutdown. - Validate user, network, persisted, and plugin data at boundaries. Keep invariant failures visible, preserve useful diagnostics, and never log credentials, subscription payloads, full share links, environments, or complete core documents. @@ -62,7 +72,9 @@ - Preserve unrelated and unstaged user changes. Do not revive deleted experiments from history or broaden a task to nearby technical debt. - Before Python work, prefer an existing root `.venv*`/`venv*` interpreter. Do not create or mutate an environment - without need. Format only touched Python files with the repository Black configuration and check them afterward. + without need. Format only touched Python files with `python -m black `, then `python -m black --check + `; `pyproject.toml` preserves string quotes. Syntax/import checks supplement behavior tests. + Documentation-only work does not require unrelated formatting or generated-file refreshes. - Preserve GPL headers, `from __future__` placement, import grouping, and established naming. Search consumers before changing public exports, plugin APIs, persisted keys/schemas, IDs, aliases, migrations, package data, or semantic exit codes. @@ -82,6 +94,9 @@ - Match evidence to the contract: round trips/migrations for models and repositories; exact transitions/signal counts for controllers; stale/cancel/rollback/cleanup paths for services; partial startup and resource reaping for runtimes; mocked OS branches for host helpers; import/discovery and packaged checks for compiler-sensitive changes. +- Report source inspection, executed tests, mocked platform evidence, and packaged validation separately. A passing + source suite does not prove native distributions or every declared Python/Qt floor. Release import checks do not + replace behavioral tests; record untested targets and compatibility gaps explicitly. - Use real Qt semantics when focus, selection, keyboard modifiers, proxy mapping, event delivery, queued callbacks, geometry, or QObject destruction matters. Prefer semantic state and destroyed/resource counts over pixel snapshots or arbitrary sleeps/RSS thresholds. @@ -101,3 +116,7 @@ future agent would choose the correct owner and test boundary. Re-read the applicable hierarchy as a fresh agent, challenge rules most likely to become stale or freeze implementation, and do not record temporary implementation details. +- In each affected scope, distinguish observed behavior from design requirements and identify tests/consumers that + can challenge the rule later. Re-read the hierarchy for circular references and rules that freeze incidental + structure. During guidance-only work, record code defects separately instead of changing production code to + satisfy the prose. diff --git a/Furious/AGENTS.md b/Furious/AGENTS.md index 889b5fe..4e3db1a 100644 --- a/Furious/AGENTS.md +++ b/Furious/AGENTS.md @@ -35,11 +35,14 @@ domain, persistence, orchestration, platform integration, and presentation; nest ## Change routing -- Controllers publish shared state and coordinate owners; they do not own transient UI or long-running worker - resources. Services do not create pages/message boxes. Widgets issue commands and present outcomes rather than - absorbing workflow orchestration. -- Plugin registries own process-lifetime plugins, descriptors, and factories—not factory-created widgets, active - runtimes, replies, or controller state. Bundled backends/extensions obey the same contracts as entry-point plugins. +- 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. 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. 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. @@ -54,3 +57,6 @@ domain, persistence, orchestration, platform integration, and presentation; nest 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. diff --git a/Furious/Actions/AGENTS.md b/Furious/Actions/AGENTS.md index 0741ae6..9c6c810 100644 --- a/Furious/Actions/AGENTS.md +++ b/Furious/Actions/AGENTS.md @@ -23,9 +23,15 @@ presentation without becoming a workflow authority. 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. -- Long-running capture/import/export presentation owns one cancellable operation context. Yield large GUI insertions or - QR rendering in bounded event-loop batches, reject callbacks after cancellation/destruction, and publish output only - while the operation context and its owned snapshot remain current. -- 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. +- Long-running capture/import/export presentation owns one cancellable operation context. Screen capture/decoding + workers return data for GUI-thread insertion and retain no transient windows. Yield large insertions in bounded + batches, reject callbacks after cancellation/destruction, and retain the captured input until terminal cleanup. QR + result generation belongs to its window; actions delegate instead of retaining a parallel exporter. +- Snapshot the intended profile identities before an asynchronous confirmation or editor opens. On acceptance + resolve those targets again; do not apply the original gesture to whatever selection happens to exist when the + dialog closes. +- 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. Use + `tests/test_qt_interactions.py`, `tests/test_ui_behavior.py`, and `tests/test_qt_lifetime.py` for focused + command/retention evidence. diff --git a/Furious/Application/AGENTS.md b/Furious/Application/AGENTS.md index a138250..b2d6af5 100644 --- a/Furious/Application/AGENTS.md +++ b/Furious/Application/AGENTS.md @@ -9,14 +9,19 @@ child-process supervisor and the inner application event loop. host integration, UI, and optional restored connection. Register cleanup as each acquisition succeeds. - Partial startup, normal exit, signals, and event-loop failure converge on one reverse-order, failure-isolating, idempotent cleanup path. `exit()` requests Qt termination; action/window/session handlers do not run cleanup directly. -- Register cleanup immediately after each successful acquisition, before the next fallible stage. Cleanup code must - tolerate a partially composed application and must not assume later repositories, controllers, UI, tray, or host - integration were created. -- Singleton election is atomic: serialize candidates, re-probe after waiting, recover only a confirmed stale endpoint, - and fail closed when ownership is uncertain, including privilege handoff. +- A stage that fails before its cleanup callback is registered must release its own partial acquisitions. The outer + cleanup stack releases completed stages; it cannot discover half-built controllers, UI, logging handlers, or + native listeners. Restore logging configuration as well as closing handlers, and keep thread-pool cleanup bounded. +- Singleton election serializes cooperating candidates, re-probes after waiting, recovers only a confirmed stale + endpoint, and fails closed when ownership is uncertain, including privilege handoff. A successful Windows + local-server listen alone does not establish exclusivity; command delivery and endpoint ownership are separate + observations. - Native session callbacks cross to the GUI thread before touching Qt-owned state. Tray, dock, System Proxy daemon, Flatpak/AppImage, and no-tray behavior are explicit platform capabilities. - The application owns the top-level window/tray wrappers; `MainWindow` owns the persistent page tree. Do not let dynamic menus, sockets, theme snapshots, workers, or partial startup owners outlive their registered cleanup stage. - Verify each acquisition failure, reverse/repeated cleanup, singleton races/commands, queued session shutdown, - tray-present/absent close policy, restored connection, and exact child/thread-pool ownership with host effects mocked. + tray-present/absent close policy, restored connection, and exact child/thread-pool ownership with host effects + mocked. Start with `tests/test_architecture_refactors.py`, `tests/test_application_process.py`, and + `tests/test_main_window_geometry.py`; use their partial-startup cases to challenge this guide when composition + changes. diff --git a/Furious/Backends/AGENTS.md b/Furious/Backends/AGENTS.md index 18667cf..96c0ad0 100644 --- a/Furious/Backends/AGENTS.md +++ b/Furious/Backends/AGENTS.md @@ -1,13 +1,14 @@ # Backend guidance -Inherit the root, package, plugin, model, and service contracts. This scope adds rules shared by all bundled proxy +Inherit the root and package guides. Consult Plugins/Models/Service for the contracts consumed by this scope. This +scope adds rules shared by all bundled proxy backends without making the richest backend the generic default. ## Common backend contract -- A backend plugin owns its configuration/document types, parsing/export, validation, editor factories, runtime factory, - and supported routing, TUN, statistics, settings, actions, or assets. Shared code asks capabilities and never branches - on core names. +- A backend supplies the subset of protocol, editor, execution, routing, TUN, statistics, settings, action, and + asset capabilities it actually supports. Shared code dispatches capabilities; a built-in backend with no + statistics, URI export, or download-test implementation remains valid. - The complete persisted core document is authoritative. Prepare logging, routing, endpoints, probes, and TUN on an independent runtime copy; failed preparation must not mutate the stored profile. - Structured editors are partial projections. Loading is observational except for a narrow documented migration; @@ -20,11 +21,13 @@ backends without making the richest backend the generic default. ## TUN and runtime policy -- Global TUN first asks the selected runtime factory to prepare native TUN on the copy. Managed native TUN replaces the - backend's runtime TUN; disabled management preserves any explicit user TUN—even malformed, so the core can reject it. - Either native case suppresses application tun2socks; only absence may permit the fallback. -- Proxy/download-test copies explicitly remove native TUN. A managed-native-TUN preparation failure is terminal rather - than permission to silently switch implementations. +- Global TUN asks the selected runtime factory about native ownership and application tun2socks. For backends + exposing native TUN, managed mode replaces that backend's TUN projection on the runtime copy; disabled management + preserves explicit user TUN, even malformed for runtime rejection. External Core instead declares host-tun2socks + opt-in; do not infer its executable's private document format or impose Xray/Hysteria2-native rules on it. +- Supported proxy/download-test preparation explicitly strips native TUN from the copied document. The generic + `proxyModeOnly` request does not sanitize arbitrary plugin configuration by itself. Required managed-native-TUN + rejection raises `TUNPreparationError`; do not silently switch implementations. - 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. - Runtime factories follow the current plugin contract: fully prepare and return one owned launch whose zero-argument @@ -41,6 +44,9 @@ backends without making the richest backend the generic default. ## Verification -- Test mapping/document/URI round trips; malformed, legacy, and unknown input; untouched-editor preservation; persisted - immutability; exact runtime/probe documents; every native/application-TUN case; startup/rollback/cleanup; assets and - statistics where applicable; plugin discovery; and repeated editor/dialog destruction. +- Test mapping/document/URI round trips; malformed, legacy, and unknown input; untouched-editor preservation; + persisted immutability; exact runtime/probe documents; every native/application-TUN case; + startup/rollback/cleanup; assets and statistics where applicable; plugin discovery; and repeated editor/dialog + destruction. Start with `tests/test_backend_editor_contract.py`, `tests/test_native_tun_semantics.py`, and + `tests/test_plugin_architecture.py`. Revalidate these shared rules against a minimally capable backend whenever a + capability changes. diff --git a/Furious/Backends/ExternalCore/AGENTS.md b/Furious/Backends/ExternalCore/AGENTS.md index ef6f6b4..a2c0325 100644 --- a/Furious/Backends/ExternalCore/AGENTS.md +++ b/Furious/Backends/ExternalCore/AGENTS.md @@ -1,6 +1,7 @@ # External Core guidance -Inherit the backend and plugin rules. This file preserves the intentionally different direct-subprocess scope for +Inherit the root, package, and common backend guides; consult Plugins for capability contracts. This file preserves +the intentionally different direct-subprocess scope for user-selected executables. ## Structured executable boundary @@ -23,7 +24,13 @@ user-selected executables. - 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. +- This is a mapping-only protocol: its explicit type discriminator selects local executable configuration, it + declares no URI schemes, and portable URI/QR export may return no result. Shared import/export UI must preserve + that capability absence. Endpoint readiness checks the configured proxy; it does not validate an arbitrary + executable's remote service. +- 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. Start with + `tests/test_external_core.py` and `tests/test_backend_editor_contract.py`. A failed final reap is a cleanup + failure to report; elapsed stop deadlines alone do not prove that the OS process or all descendants have exited. diff --git a/Furious/Backends/Hysteria1/AGENTS.md b/Furious/Backends/Hysteria1/AGENTS.md index bda7549..f695e2c 100644 --- a/Furious/Backends/Hysteria1/AGENTS.md +++ b/Furious/Backends/Hysteria1/AGENTS.md @@ -1,6 +1,7 @@ # Hysteria 1 guidance -Inherit the common backend and plugin rules. This scope exists to preserve Hysteria 1's legacy flat schema and lifecycle +Inherit the root, package, and common backend guides; consult Plugins for capability contracts. This scope exists to +preserve Hysteria 1's legacy flat schema and lifecycle without importing assumptions from Hysteria 2. - Hysteria 1 is the legacy flat client schema and `hysteria://` share-link backend. Do not import Hysteria 2 nested @@ -15,6 +16,11 @@ without importing assumptions from Hysteria 2. falling through another backend’s policy. - Treat tolerated legacy values as input compatibility, not as permission to rewrite the persisted document during inspection. Runtime validation may reject what observational editor loading must still preserve. +- Routing ACL/MMDB launch inputs remain distinct from the stored connection JSON. A prepared runtime advertises its + local HTTP readiness endpoint separately from child liveness. The built-in factory has no statistics provider; + shared UI must handle that absence instead of treating it as a failed connection. - 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. + absence or malformed paths, asynchronous readiness and rollback, core-exit translation, application-TUN policy, + and repeated editor/runtime cleanup. Use `tests/test_hysteria1_protocol.py`, + `tests/test_backend_editor_contract.py`, and `tests/test_connection_startup_async.py`. Revise this guide with + intentional schema evolution instead of freezing tolerated historical input into a universal backend rule. diff --git a/Furious/Backends/Hysteria2/AGENTS.md b/Furious/Backends/Hysteria2/AGENTS.md index 4532b30..b428b8e 100644 --- a/Furious/Backends/Hysteria2/AGENTS.md +++ b/Furious/Backends/Hysteria2/AGENTS.md @@ -1,6 +1,7 @@ # Hysteria 2 guidance -Inherit the common backend and plugin rules. This scope owns Hysteria 2's nested upstream document, native-TUN +Inherit the root, package, and common backend guides; consult Plugins for capability contracts. This scope owns +Hysteria 2's nested upstream document, native-TUN capability, statistics, and editor projection. ## Native document and editor projection @@ -15,14 +16,20 @@ capability, statistics, and editor projection. ## 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. +- 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. Managed preparation currently resolves server addresses synchronously; do not describe the whole native-TUN + stage as event-driven merely because connection readiness is asynchronous. +- The statistics provider is a process-lifetime capability; the runtime captures a configured server-API target and + sampling owns its monitor/query lifetime. API URL, client ID, and authorization secret are distinct from client + connection credentials. Keep requests bounded, validate counters, and never log the secret or infer statistics + from merely having a running Hysteria2 process. - Capability presence is independent: native TUN, statistics, actions, settings, routing, and protocol editing must continue to work or fail through their own declared contracts rather than being inferred from the runtime type. -- 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. +- 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. Start with + `tests/test_hysteria2_compatibility.py`, `tests/test_native_tun_semantics.py`, and + `tests/test_backend_editor_contract.py`. diff --git a/Furious/Backends/Xray/AGENTS.md b/Furious/Backends/Xray/AGENTS.md index 98dea91..79cb4c7 100644 --- a/Furious/Backends/Xray/AGENTS.md +++ b/Furious/Backends/Xray/AGENTS.md @@ -1,6 +1,7 @@ # Xray guidance -Inherit the common backend and plugin rules. This scope owns Xray's full JSON preservation, routing/assets/statistics, +Inherit the root, package, and common backend guides; consult Plugins for capability contracts. This scope owns Xray's +full JSON preservation, routing/assets/statistics, and protocol/transport/TLS projections. ## Full-document preservation @@ -17,14 +18,20 @@ and protocol/transport/TLS projections. ## 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. +- 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 preparation replaces inbounds with its test surface. Verify + the prepared document rather than assuming `proxyModeOnly` alone removes user TUN from every factory input. - 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. -- Asset downloads stage bytes and digest verification before replacing the live file. A failed request, checksum, or - write leaves the prior usable asset intact and reports the failure without pretending an update succeeded. -- 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. +- Runtime asset updates stage bytes and digest verification before atomic replacement. Failure preserves the prior + usable file. Distinguish this updater from `Deploy.py --download`, whose download/integrity behavior must be + inspected separately; shared filenames do not make the two mechanisms equivalent. +- Routing selection IDs, user routing documents, and translated built-in labels are different contracts. Preserve + custom document content and named-profile identity while composing runtime routing/API statistics. +- 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. Use `tests/test_xray_asset_download.py`, + `tests/test_native_tun_semantics.py`, and `tests/test_backend_editor_contract.py`. Update this scope when a + verified backend capability changes intentionally. diff --git a/Furious/Controllers/AGENTS.md b/Furious/Controllers/AGENTS.md index 6167282..4a22802 100644 --- a/Furious/Controllers/AGENTS.md +++ b/Furious/Controllers/AGENTS.md @@ -7,25 +7,32 @@ transitions, not owners of execution resources or presentation objects. - 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. +- `ConnectionController` is the sole connection state machine. A GUI start remains `Connecting` while one + generation- checked `ConnectionManager` transaction acquires readiness/TUN resources. The selected live profile is + exposed during `Connecting`; successful runtime commit precedes System Proxy setup and `Connected`. Failure resets + the active profile. 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. - A startup completion must belong to the current controller generation before it can change state, active profile, System Proxy, or interaction gating. Typed runtime failures keep their semantic reason; cancellation and supersession are not rewritten as generic connection errors. -- `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. +- `RoutingController` owns available capability options plus selected/persisted routing. Distinguish a newly + selected repository profile from the active-profile reference and the independent runtime document; 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. Startup + registration persists only after host success; other preferences may apply immediately or on the next connection. + Preserve each setting's actual application timing instead of imposing one transaction order on all preferences. +- System Proxy helpers currently log some host failures without raising. Controller exception-path tests prove + recovery when an error reaches the controller, not that every OS failure is propagated. Keep desired proxy mode + distinct from observed host state when evolving this boundary. ## 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. +- 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. + Start with `tests/test_controllers.py`, `tests/test_connection_startup_async.py`, and the shared-state cases in + `tests/test_qt_interactions.py`. diff --git a/Furious/Core/AGENTS.md b/Furious/Core/AGENTS.md index 78c0457..8010b6e 100644 --- a/Furious/Core/AGENTS.md +++ b/Furious/Core/AGENTS.md @@ -1,13 +1,14 @@ # Embedded runtime guidance -Inherit the root, package, interface, and service rules. This scope owns reusable embedded execution machinery and +Inherit the root and package guides. Consult Interface for runtime contracts and Service for connection ownership. +This scope owns reusable embedded execution machinery and application tun2socks, while connection policy remains outside it. - `Core` supplies shared multiprocessing runtime machinery, bounded output transport, and application tun2socks. External Core owns its separate direct `subprocess.Popen`; neither layer owns controller, repository, UI, or protocol policy. -- A launch spec describes only validated child construction, never semantic connection readiness. Runtime preparation - completes before construction; the asynchronous connection transaction observes endpoints/process survival and - commits later. Keep any synchronous waiting isolated as an explicit compatibility path. +- A launch spec describes prepared child construction, never semantic connection readiness. Serialization and launch + arguments are prepared before execution starts; constructors may create owned timers/queues that still need + disposal if execution never starts. The service observes endpoints/process survival and commits later. - `CoreRuntime` execution state, typed terminal exit, and readiness are separate contracts. A process becoming alive is not proof that its proxy/TUN endpoint is ready, while a readiness timeout must not overwrite an already observed typed exit. @@ -19,5 +20,8 @@ application tun2socks, while connection policy remains outside it. per-turn drain work; draining continues independently of Log-page visibility and backs off only when idle. - Parentless timers are acceptable only with a durable runtime owner and explicit disposal. Leaving the manager pool must not leave timers, callbacks, queues, or process handles alive. -- Verify invalid target/serialization, failed spawn, early exit, readiness compatibility, burst output bounds/backoff, - normal and forced stop, repeated disposal, and absence of residual children, handles, timers, queues, or callbacks. +- Verify invalid target/serialization, failed spawn, early exit, readiness compatibility, burst output + bounds/backoff, normal and forced stop, repeated disposal, and absence of residual children, handles, timers, + queues, or callbacks. Start with `tests/test_runtime_lifecycle.py` and `tests/test_connection_startup_async.py`; + output/process stress lives in the tiers documented by `tests/README.md`. Review output admission and draining + together when changing backpressure. diff --git a/Furious/Data/AGENTS.md b/Furious/Data/AGENTS.md index 9ea6273..c795ce1 100644 --- a/Furious/Data/AGENTS.md +++ b/Furious/Data/AGENTS.md @@ -16,13 +16,17 @@ application-data or settings directory. ## Local endpoint map -- The MapLibre document is an offline/privacy boundary. Keep executable code, style, glyphs, sprites, and required data - local and package-resolvable; do not add trackers or runtime CDN dependencies. Missing optional map detail must degrade - visibly but must not crash the WebEngine renderer or the application. +- MapLibre JavaScript/CSS and the host bridge are bundled; the style requests vector tiles and glyphs from + `tiles.openfreemap.org`. This is not an offline map. Keep executable code local, preserve attribution, and review + the HTML content-security policy and the widget's attribution-link validation when changing network resources or + links. Missing tiles/network detail must degrade without crashing the renderer or the application. - Linux Essentials-only builds deliberately operate without WebEngine; map consumers must retain their non-WebEngine fallback. macOS/Windows packaged paths may include WebEngine and must resolve all local resources from the bundle. ## Verification -- Verify the real consuming backend/widget, source and packaged path resolution, package-data/Nuitka inclusion, integrity - and failure behavior, and license presence. Tests use fixtures or mocked downloads, never live asset refreshes. +- Verify the real consuming backend/widget, source and packaged path resolution, package-data/Nuitka inclusion, + integrity and failure behavior, and license presence. Tests use fixtures or mocked downloads, never live asset + refreshes. `tests/test_endpoint_info.py` and `tests/test_public_api.py` cover map/resource consumers; release + artifacts require their own inclusion checks. Revalidate provenance/network claims when an asset provider or + loader changes. diff --git a/Furious/Extensions/AGENTS.md b/Furious/Extensions/AGENTS.md index 75074ac..89653f9 100644 --- a/Furious/Extensions/AGENTS.md +++ b/Furious/Extensions/AGENTS.md @@ -1,21 +1,27 @@ # Bundled extension guidance -Inherit the root, package, and plugin guides. This scope covers host-shipped non-runtime plugins and must not gain +Inherit the root and package guides; consult Plugins for capability and registration contracts. This scope covers +host-shipped non-runtime plugins and must not gain private authority merely because the code is bundled. -- `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. +- `Extensions` contains host-shipped plugins that are not proxy runtimes. They register through the same public API + and lifecycle as entry-point plugins. New extension contracts must be usable without private + repository/controller/UI access; bundled location is not permission to bypass the public boundary. - `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. + `SubscriptionResult` envelope; nested mappings are not necessarily deeply immutable. 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. + 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. Standard decoders opt into worker execution; that declaration covers + all shared parser state and caches, not merely absence of widgets in the immediate method. - Decoder output is descriptive, not a repository transaction. It cannot assign live profile identity, mutate a subscription group, cancel tests, reconnect, or publish UI state; those decisions remain at the import/manager commit boundaries. - 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. + guide with the decoder contract rather than giving bundled formats permanent special treatment. Use + `tests/test_plugin_architecture.py` and `tests/test_subscription_scalability.py`; decoder success is not + authorization to import a protocol whose descriptor excludes subscriptions, such as local executables. diff --git a/Furious/Externals/AGENTS.md b/Furious/Externals/AGENTS.md index a3e985f..ab77297 100644 --- a/Furious/Externals/AGENTS.md +++ b/Furious/Externals/AGENTS.md @@ -7,11 +7,13 @@ human-reviewed translations. - `Furious/Externals/GenTranslation.py` is generator-managed, but its language values and `isReviewed` flags are curated data. Repository-root `Translation.py` owns source extraction and catalog structure; neither file is disposable. -- Run `Translation.py --target ` with the repository interpreter after changing translatable source or curated - wording. It rebuilds source membership, drops stale keys, preserves reviewed target text, initializes unresolved text, - detects target collisions, and writes deterministic key order. -- Entry key order is `source`, language keys retained by the generator, then `isReviewed`. `source` contains - deduplicated fully qualified modules; do not curate that list manually because extraction rebuilds it. +- Run `python Translation.py --target ` with the repository interpreter for an intentional + extraction/update. It rebuilds source membership, drops stale keys, preserves reviewed target text, and reports + collisions. Automatic translation is currently disabled: unresolved/unreviewed target values may be replaced with + the source text. Review the diff before treating the command as a harmless refresh, especially with `--ignore`. +- Existing dictionary order is generally preserved; the generator does not enforce a universal field order and + source traversal can affect newly discovered entries. Keep diffs stable without claiming canonical sorting. + `source` contains deduplicated fully qualified modules and is rebuilt by extraction rather than manually curated. - Inspect the full diff. Preserve deliberate translations/review flags, HTML/newline semantics, and natural RU/ZH meaning; mark an entry reviewed only after a human has verified it. Do not hand-maintain the generated `source` module list. @@ -29,7 +31,12 @@ human-reviewed translations. ## Verification -- Run extraction for every affected language, review collisions/stale removal/order and the catalog diff, then run it a - second time to prove stability. Exercise runtime lookup and affected UI retranslation under explicit locales. -- Translation generation is a scoped repository mutation: do not run it as an incidental formatter, and do not accept - broad catalog churn without tracing each changed source literal or intentional stale-key removal. +- Run extraction for every affected language, inspect collision/unreviewed diagnostics and the complete catalog + diff, then run it again to check stability. Collision and write failures are logged rather than guaranteed to + produce a nonzero process exit; exit status alone is not validation. Exercise runtime lookup and UI retranslation + under explicit locales; `tests/test_models_and_services.py` and `tests/test_ui_behavior.py` cover extraction/UI + consumers. +- Translation generation is a scoped repository mutation: do not run it as an incidental formatter, and do not + accept broad catalog churn without tracing each changed source literal or intentional stale-key removal. Update + this guide when extraction or review semantics change; do not generalize generator-managed membership into a ban + on curated text. diff --git a/Furious/Frozenlib/AGENTS.md b/Furious/Frozenlib/AGENTS.md index e0a8ac6..e80506d 100644 --- a/Furious/Frozenlib/AGENTS.md +++ b/Furious/Frozenlib/AGENTS.md @@ -9,21 +9,28 @@ for unrelated application orchestration to accumulate in a broad helper namespac - `Globals` exposes only deliberate application-lifetime owners. Accessors may be absent during partial startup, isolated tests, or teardown; do not add fallback global owners that create competing lifecycles. - `AppSettings` keys include preferences and encoded repository blobs. Preserve names, defaults, string/binary - encodings, migrations, and import-time registration. When a preference represents a host side effect, persist success - only after the host operation succeeds. + encodings, migrations, and import-time registration. Distinguish desired preferences from confirmed host effects; + startup-registration success is persisted only after its helper reports success. - Keep proxy, DNS, routing, TUN, startup registration, session callbacks, external commands, and platform detection here or behind a runtime boundary so tests can replace them completely. Windows, macOS, Linux, Flatpak, AppImage, and older platform paths are distinct capabilities; never generalize from the current host. -- A host mutation returns success only after the actual platform operation completed. The owning controller/service - decides rollback and persistence; low-level helpers do not silently update shared UI state or convert an unsupported - platform into a successful no-op. +- Check each helper's real result contract. Startup registration and some routing helpers return Booleans; System + Proxy set/off currently log failures and return no success value. Script-mode startup registration intentionally + does nothing. Do not infer confirmed host state from absence of an exception or generalize one helper's semantics + to all. New mutation APIs should report actionable success/failure to the owning controller/service. - Prefer argument vectors over shell strings. Each caller owns any responsiveness/cleanup timeout appropriate to its context; build-time commands and GUI-time host mutation do not share one universal timeout policy. +- Windows proxy calls, Linux desktop settings/host bridging, and macOS network-service operations are distinct + paths. Application tun2socks host routing differs from backend-native TUN; preserve privilege, DNS restoration, + and managed route cleanup for the selected path. Some helpers block synchronously and need caller-level + responsiveness review. - Own exact native threads/processes/handles and clear stale daemon references. Externally keyed caches are bounded and no cache/weak pool captures QObject instances or bound methods accidentally. - `CleanupOnExit` and translation/theme/connection pools are registries, not owners. Their legacy de-duplication behavior is a compatibility constraint; resource-owning repeated instances need an explicit owner/cleanup stage. - `AppResources.py` is generated from `Resources.qrc` and referenced assets. Change the manifest/input files and regenerate with the compatible PySide6 resource compiler; never hand-edit generated resource code. -- Verify every affected OS branch with mocked host calls, plus persistence-on-failure, bounded cleanup, import-time side - effects, sensitive logging, stale handles/daemons, and cache growth. +- Verify every affected OS branch with mocked host calls, plus persistence-on-failure, bounded cleanup, import-time + side effects, sensitive logging, stale handles/daemons, and cache growth. Use `tests/test_frozenlib.py` and the + mocked platform cases in `tests/test_connection_startup_async.py`; update this guide when observed host contracts + change. diff --git a/Furious/Interface/AGENTS.md b/Furious/Interface/AGENTS.md index 56ee576..8b49c73 100644 --- a/Furious/Interface/AGENTS.md +++ b/Furious/Interface/AGENTS.md @@ -9,9 +9,9 @@ satisfy without importing application composition or concrete backends. - 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. -- Keep versioned contract changes explicit. Reject unsupported shapes at the registration/boundary layer, update every - bundled implementation and compatibility export together, and avoid adapters that let two conflicting ownership - models coexist indefinitely. +- Interface contracts and the separately versioned plugin API are different compatibility surfaces. Reject + unsupported shapes at their owning boundary and update implementations/exports together; do not invent a version + gate for every Python interface or remove an established adapter without tracing its callers. - `CoreRuntime` is mechanism-neutral: embedded multiprocessing, direct `subprocess`, or an in-process binding can satisfy it. It owns execution only: zero-argument start, passive liveness, typed terminal events, and bounded idempotent stop/dispose. Preparation, serialization, readiness, and startup transactions belong outside this contract. Bind its @@ -20,8 +20,12 @@ satisfy without importing application composition or concrete backends. - `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. +- `ApplicationRunner.ExitCode` is a process-boundary protocol. Model encoders may raise, while configuration + construction deliberately captures diagnostics; do not impose one blanket exception convention on those different + contracts. +- Runtime liveness is observational: querying it must not consume an exit, transfer ownership, or dispatch + callbacks. Keep semantic startup errors separate from raw process codes and readiness timeouts. +- 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. Start with `tests/test_interface.py` and + `tests/test_runtime_lifecycle.py`; include `tests/test_public_api.py` when imports or exports change. diff --git a/Furious/Models/AGENTS.md b/Furious/Models/AGENTS.md index 36faad8..3d91d33 100644 --- a/Furious/Models/AGENTS.md +++ b/Furious/Models/AGENTS.md @@ -19,13 +19,20 @@ Qt presentation, plugin discovery, or workflow execution. or invoking a backend runtime. - `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. +- Profile ID, object identity, subscription source/key, connection fingerprint, display text, and row position + answer different questions. Fingerprints cover only the connection document, not user metadata; they require + deterministic JSON-compatible values and reject non-finite numbers. A metadata edit need not invalidate connection + testing. +- Subscription membership (`subscriptionSource`) and remote ownership (`subscriptionManaged` plus its matching key) + are separate. Legacy migration may infer ownership where the flag was absent; current locally grouped profiles + must remain local. Preserve that distinction through copies, moves, and metadata aliases. ## 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. +- 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. `tests/test_models_and_services.py`, `tests/test_repository_contracts.py`, and + `tests/test_profile_test_jobs.py` exercise these values across persistence and asynchronous consumers. diff --git a/Furious/Plugins/AGENTS.md b/Furious/Plugins/AGENTS.md index 76ee743..a70a524 100644 --- a/Furious/Plugins/AGENTS.md +++ b/Furious/Plugins/AGENTS.md @@ -1,6 +1,7 @@ # Plugin guidance -Inherit the root, package, and interface guides. This scope owns capability definitions, atomic registration, dispatch, +Inherit the root and package guides; consult Interface guidance for runtime/storage contracts. This scope owns +capability definitions, atomic registration, dispatch, and plugin lifecycle; concrete backend policy remains in each implementation. ## Contracts and registry @@ -10,30 +11,39 @@ and plugin lifecycle; concrete backend policy remains in each implementation. adding backend-name branches or a parallel registry. - The registry normalizes and validates a plugin's complete contribution before committing indexes. Duplicate IDs or schemes, incompatible API versions, invalid descriptors, and initialization failure leave existing providers intact. -- Host plugin types register before external entry-point discovery. Discovery and bundled registrations remain - deterministic, side-effect-light, and literal enough for source, wheel, and Nuitka inclusion. +- Host plugin types register before external entry-point discovery. Bundled registrations are explicit for source, + wheel, and Nuitka inclusion. External entries currently follow metadata enumeration order; do not promise sorted + discovery or rely on it for precedence. Registration is atomic per plugin, not across a multi-plugin entry point. - Optional provider failure is isolated when another candidate can continue; required-operation failure remains observable with plugin/capability identity and without secret configuration data. ## Ownership and compatibility -- Registries own process-lifetime plugin instances, capabilities, factories, descriptors, and immutable metadata. They - never own created editors/dialogs, active runtimes, replies, repository collections, or controller state. Factories - return a fresh owned result per request. +- Registries own plugin/capability instances and descriptors; created editors and runtimes transfer to their + callers. Capabilities may retain explicitly owned reusable services with shutdown obligations. Do not cache + created transient UI in the registry or treat the registry as the connection/repository authority. - Once a runtime factory returns a valid launch, the caller acquires that exact runtime even if start raises, so partial resources can be stopped/disposed. Return no runtime only when none was acquired. - Plugin/model data is untrusted at the boundary even though installed code is trusted to execute. Validate types, ownership, required fields, and QObject validity before publishing results. -- API and model layers never import concrete plugins. Bundled backends and extensions obey the same public lifecycle as - entry-point plugins; do not give bundled code hidden repository/UI side channels. +- API and model layers never import concrete plugins. Bundled backends/extensions obey the public lifecycle; their + existing host-global integrations must not become prerequisites for external plugins. - Evolve contracts additively when practical. Before a breaking change, inspect external discovery, compatibility exports, every bundled implementation, tests, and compiled inclusion; do not infer compatibility from built-ins alone. - A capability contract is generic only when an external plugin can satisfy it without importing private application state. Backend-specific defaults, settings keys, document branches, and host assumptions stay behind the provider rather than becoming undeclared registry requirements. - API-version-3 runtime factories return `PreparedRuntime` directly. The runtime is fully prepared before return, - starts with zero arguments, raises typed startup failures, and exposes readiness separately; do not add legacy launch - adapters, Boolean startup side channels, or alternate factory-result shapes. + starts with zero arguments, raises typed startup failures, and exposes readiness separately; do not add legacy + launch adapters, Boolean startup side channels, or alternate factory-result shapes. The registry's existing + synchronous `startCoreRuntime()` wrapper separately returns runtime/success for compatibility; preserve ownership + on start failure. +- `TUNPreparationError` is the explicit terminal native-TUN failure contract. Other provider exceptions currently + log and return an unhandled result; required TUN rejection must use the typed error rather than assume all + exceptions stop fallback. Optional capabilities may be absent; an External Core need not implement statistics or + download probes. +- Frozen result envelopes are not recursively immutable: embedded configuration/metadata mappings still require copy + isolation before mutation or worker handoff. - Capability instances default to GUI-thread-only for background subscription preparation. A decoder or protocol handler opts into worker execution only after its parsing, validation, caches, globals, and Qt usage are audited as safe for concurrent copied inputs; keep unclassified third-party capability execution on the GUI thread. @@ -41,5 +51,7 @@ and plugin lifecycle; concrete backend policy remains in each implementation. ## Verification - Cover discovery/order, API version and duplicate rejection, each changed dispatch path, registration rollback, - reverse idempotent shutdown, provider failure isolation, invalid factory results, repeated transient creations without - registry retention, and packaged discovery/import. + reverse idempotent shutdown, provider failure isolation, invalid factory results, repeated transient creations + without registry retention, and packaged discovery/import. `tests/test_plugin_architecture.py` and + `tests/test_public_api.py` anchor compatibility; challenge this guide when API versions or capability ownership + change. diff --git a/Furious/Qt/AGENTS.md b/Furious/Qt/AGENTS.md index 1cc1a3a..4af4809 100644 --- a/Furious/Qt/AGENTS.md +++ b/Furious/Qt/AGENTS.md @@ -21,12 +21,16 @@ primitives; pages and services consume them without creating parallel registries close/hide/destroy path, and every timer, model, delegate, action, menu, animation, effect, event filter, reply, worker, callback, cache, and signal edge that may extend the lifetime. - Reusable windows retain one explicit owner and reset on reopen. One-shot dialogs use `AppQTransientDialog` or - `AppQMessageBox`; async presentation retains them through native destruction, not merely `finished`. + `AppQMessageBox`; `open()` registers their strong async owner through native destruction and releases the token on + the next event-loop turn. Plain dialog `show()` does not enter that registry and needs another durable owner. + `finished` ends interaction, not native lifetime; operation context may be released then only if later callbacks + do not need it. - `AppQDialog`/`AppQMainWindow` registries bridge asynchronous presentation/visibility; they are not substitute application owners. Registry cleanup captures opaque tokens, never the object being released. -- A Qt parent alone does not prove the Python wrapper or logical feature lifetime. Conversely, `.show()` does not retain - an unparented top-level wrapper. Do not solve ambiguity by global retention, indiscriminate delete-on-close, routine - `gc.collect()`, or broad deleted-wrapper suppression. +- A Qt parent alone does not prove the Python wrapper or logical feature lifetime. Bare Qt `.show()` does not retain + an unparented wrapper; `AppQMainWindow.show()` adds its own visible-window retention until accepted close. Do not + solve ambiguity by global retention, indiscriminate delete-on-close, routine `gc.collect()`, or broad + deleted-wrapper suppression. ## Signals, threads, and async Qt work @@ -36,8 +40,11 @@ primitives; pages and services consume them without creating parallel registries through a compiled bound method or a closure/partial that strongly captures it. Use `connectWeakly()` with a static method name and `sender=` when the sender is independent/longer-lived; use `forwardSender=True` instead of relying on `QObject.sender()` and `singleShotWeakly()` for deferred named-method delivery. -- Direct bound-method connections are acceptable only for deliberately long-lived receivers when retention is - intentional. `AppQAction.callback` is strong by design, so the action owner cannot outlive the captured receiver. +- Direct connections are appropriate for deliberately shared persistent lifetimes; syntax alone does not prove a + leak. Recheck the selected Nuitka/PySide6 callback protection when the toolchain changes. Static weak method names + are runtime contracts, so renames must update registrations and tests. Weak dispatch itself does not marshal + arbitrary worker calls to the GUI thread; choose an explicit queued owner-thread delivery boundary. +- `AppQAction.callback` is strong by design, so the action owner cannot outlive the captured receiver. - Every `QNetworkReply` has one manager/context owner, one freshness rule, and one terminal deletion path. Do not attach ad-hoc attributes to third-party Qt objects or multiply timers/connections across show/hide cycles. - Queued delivery never transfers ownership implicitly. The sender may finish before delivery, so callbacks resolve a @@ -52,5 +59,8 @@ primitives; pages and services consume them without creating parallel registries or destruction, construct real widgets and use `QTest` plus the real event loop. Test semantic state and lifecycle, not private coordinates or pixel-perfect screenshots. - For lifetime-sensitive changes, repeat open/close/accept/reject paths and assert destroyed signals, weak wrappers, - registries, timers, callbacks, replies, threads, handles, and child counts return to baseline. Run a representative - Nuitka probe when compiled callback retention or packaged-only behavior is part of the defect. + registries, timers, callbacks, replies, threads, handles, and child counts return to baseline. Run a + representative Nuitka probe when compiled callback retention or packaged-only behavior is part of the defect. + Start with `tests/test_qt_lifetime.py`, `tests/test_dialog_geometry.py`, and `tests/test_main_window_geometry.py`; + use the `tests/fixtures/editor_lifetime_probe.py` fixture for compiled investigation. Treat unrun packaged probes + as unverified, and update these rules when measured ownership or the toolchain changes. diff --git a/Furious/Repository/AGENTS.md b/Furious/Repository/AGENTS.md index 3e13ba7..aa6d16f 100644 --- a/Furious/Repository/AGENTS.md +++ b/Furious/Repository/AGENTS.md @@ -1,7 +1,7 @@ # Repository guidance -Inherit the root, package, interface, and model guides. This scope owns restoration, migration, ordering, and durable -collection commits; workflows and presentation remain outside it. +Inherit the root and `Furious/AGENTS.md`. Consult the Interface and Models guides when changing their contracts. +This scope owns restoration, migration, ordering, and persistence; workflows and presentation remain outside it. - Repositories restore, migrate, order, and persist profiles, subscriptions, routings, and TUN settings. They do not own network workflows, controller state, test schedulers, or presentation. @@ -12,12 +12,16 @@ collection commits; workflows and presentation remain outside it. Active row/index and display text are compatibility/presentation state, not identity. - A restore failure remains observable. Automatic cleanup must not replace unreadable persisted bytes with an empty fallback; only an explicit successful replacement may do so. -- Stage fallible decode, migration, or reconciliation before deterministic mutation of the live collection. A - subscription commit changes only that group: matched managed profiles retain stable object/profile identity and local - metadata, removed profiles are marked stale, and indexes/order update atomically. -- Persistence is part of the repository commit contract, not evidence that later host/controller side effects succeeded. - Callers report post-commit failures separately and must not claim the durable mutation rolled back when it did not. +- Stage fallible decode/migration before live mutation. Subscription reconciliation currently belongs to + `Service/SubscriptionSync.py` and commits through the compatibility live collection: matched managed profiles + retain object/profile identity and local metadata, removed profiles become stale, and unrelated groups remain + intact. Do not add a second reconciliation algorithm here merely because persistence belongs to this scope. +- Distinguish a live-collection commit from serialization/flush and subsequent controller effects. The compatibility + collection can change before it is flushed; a successful in-memory synchronization is not proof of an atomic disk + transaction. Preserve explicit flush/cleanup behavior and report failures at the boundary that actually failed. - Moving a profile between subscription displays does not automatically make it remotely managed; preserve the explicit distinction between local membership and synchronization ownership. - Verify legacy/current/unknown-field round trips, malformed roots, restore-failure preservation, ordering/stable - identity, group isolation, reconciliation commit behavior, and persistence in temporary QSettings namespaces. + identity, group isolation, reconciliation commit behavior, and persistence in temporary QSettings namespaces. Use + `tests/test_repository_contracts.py` and `tests/test_subscription_sync.py` to revalidate this scope. Reordering a + filtered view must preserve hidden slots and relocate activation by profile ID, not by its former row. diff --git a/Furious/Service/AGENTS.md b/Furious/Service/AGENTS.md index adbf5c7..95e679e 100644 --- a/Furious/Service/AGENTS.md +++ b/Furious/Service/AGENTS.md @@ -1,12 +1,14 @@ # Service guidance -Inherit the root, package, model, repository, plugin, core, and Qt lifetime rules. This scope owns multi-stage workflows -and temporary resources, never durable collections, shared transition authority, or presentation. +Inherit the root and package guides. Consult Models/Repository for data contracts, Plugins/Core for execution, and Qt +for lifetime primitives. This scope owns multi-stage workflows and temporary resources. ## Workflow ownership -- Services own workflows and temporary resources; controllers own shared state, repositories own durable collections, - and UI owns presentation. Services may use Qt signals/networking but do not create pages or message boxes. +- Services own workflows and temporary resources; controllers own shared state, repositories own durable + collections, and UI owns presentation. Prefer outcome signals/callbacks for new service APIs. `UpdateManager` + still creates update dialogs as a compatibility path; preserve its public behavior until presentation is + deliberately moved to a UI owner. - Give each QObject service, worker, reply, timer, pool, thread, runtime, process, cache, and callback context one durable owner and bounded idempotent cleanup. Construct Qt services only after an application exists. - Inject repositories/providers/clients/runtime factories where practical. Stage results, prove freshness, and commit @@ -17,10 +19,13 @@ and temporary resources, never durable collections, shared transition authority, ## Connection and network workflows -- GUI connection startup is a generation-checked transaction over a runtime copy: prepare TUN policy, launch and observe - the primary runtime, resolve DNS, acquire optional tun2socks, mutate host networking in platform order, then commit. - Failure/cancellation rolls back only attempt-owned runtimes and host changes. The synchronous start path is a - compatibility boundary, not the default GUI mechanism. +- GUI connection startup is a generation-checked transaction over a runtime copy: prepare TUN policy, launch and + observe the primary runtime, acquire optional tun2socks/DNS resources, and mutate host networking in platform + order before commit. Preserve Windows runtime-before-device, Linux device-before-runtime, and macOS + survival-before-DNS ordering. Failure/cancellation releases attempt-owned runtimes and registered host cleanup. + The synchronous start path is a compatibility boundary, not the default GUI mechanism. Timed readiness/DNS + continuations do not make synchronous platform commands or backend preparation interruptible; audit those calls + and shared route bookkeeping separately. - Construct a runtime event router before asking a plugin to create its runtime. One lease owns the runtime/router from acquisition through attempt ownership, commit, and reverse-order release; commit changes logical delivery without replacing the runtime callback. Worker-thread exits are queued to the router's Qt thread, delivered at most once, and @@ -30,24 +35,33 @@ and temporary resources, never durable collections, shared transition authority, connectivity, endpoint, subscription, and asset requests own their exact reply and reject stale generations. - Subscription stages remain separate: decoders return neutral items; import constructs profiles/metadata; synchronization prepares one group reconciliation; the manager owns request/schedule generations and commits it. - Large payload import and reconciliation preparation run in the manager's bounded pool over copied payload/profile - data. Workers never read live repositories or Qt models; the GUI thread verifies the full source signature and group - revision, commits while preserving live profile identity/local metadata, then publishes coalesced status/structure. - Post-commit reconnect/test invalidation failure is reported without undoing the committed profiles. + Worker-safe payload import and reconciliation preparation run in the manager's bounded pool over copied data; + unclassified plugin parsers stay on the GUI compatibility path. Workers never read live repositories or Qt models; + the GUI thread verifies the full source signature and group revision, commits while preserving live profile + identity/local metadata, then publishes coalesced status/structure. Post-commit reconnect/test invalidation + failure is reported without undoing the committed profiles. Here commit means live reconciliation; repository + flush and status persistence are separate boundaries, not one disk transaction. - Provider-reported subscription usage/expiry metadata is untrusted advisory input. Parse it with strict bounds at the network boundary and commit or clear it only alongside a successful current synchronization; failed synchronization preserves the last successful metadata. - Log transport, traffic collection, and metric history remain bounded and independent of page visibility. Rendering may be lazy; collection/draining ownership is not. -- Logging accepts concurrent producers through one bounded ordered model; runtime-only clearing and retention cannot - block producers with unbounded synchronous traversal. Metrics sampling owns its worker/future generation and discards - results after disconnect, disablement, replacement, or shutdown. +- Logging accepts concurrent producers through one globally ordered model with count, total-character, and per-entry + limits. Whole-stream clearing swaps generations; retired entries are reclaimed in bounded batches under retention + budgets. Selective category clearing can cost O(k); do not claim every clear is constant-time. +- Log cursors are opaque and filter-specific. A generation change requires a reset; retention-only eviction supplies + a new first-retained sequence so presenters can prune their prefix without rebuilding history. Capture entries and + the next cursor atomically, and coalesce notifications without losing producer updates. +- Metrics sampling owns its worker/future generation and rejects results after disconnect, disablement, replacement, + or shutdown. Cancellation cannot stop an already-running plugin query: monitor contracts must bound blocking work. + Normalize cumulative-counter resets before history aggregation; clearing usage must not erase speed history. ## Profile testing -- `ProfileTestManager` is the sole result write-back boundary. A job captures stable profile ID, connection fingerprint, - snapshot, ownership, and explicit options; workers return values and the manager resolves the current target before - mutating latency/speed. +- `ProfileTestManager` is the sole result write-back boundary. A job captures stable profile ID, connection + fingerprint, snapshot, ownership, and explicit options; workers return values and the manager resolves the current + target before mutating latency/speed. Freshness currently resolves ID plus connection fingerprint; subscription + ownership drives explicit group invalidation, not an implicit row or metadata equality test. - Repository changes reconcile queued/running jobs. A successful subscription commit cancels that group's pending and active tests, stale-marks non-cancellable calls, clears only that group's current results, and leaves manual/other-group work untouched. @@ -62,5 +76,8 @@ and temporary resources, never durable collections, shared transition authority, - Cover success plus invalid, stale, superseded, timeout, cancellation, partial acquisition, hidden-page, reentrant, and repeated-shutdown paths. Assert current identity at write-back and exact cleanup of pools, threads, sockets, replies, timers, ports, runtimes, callbacks, and host mutations. -- Test pre-commit failure with unchanged live/persisted state separately from post-commit side-effect failure. Never use - a broad rollback assertion to conceal which boundary actually committed. +- Test pre-commit failure with unchanged live/persisted state separately from post-commit side-effect failure. Never + use a broad rollback assertion to conceal which boundary actually committed. Use `tests/README.md` for + workflow-specific modules; `test_log_manager_generation.py`, `test_profile_test_jobs.py`, + `test_subscription_sync.py`, and `test_connection_startup_async.py` challenge the high-risk contracts above. + Update this scope with verified changes to commit, cancellation, or ownership boundaries. diff --git a/Furious/Utility/AGENTS.md b/Furious/Utility/AGENTS.md index cfae2b9..59c6366 100644 --- a/Furious/Utility/AGENTS.md +++ b/Furious/Utility/AGENTS.md @@ -8,14 +8,19 @@ general-purpose utility bucket. - `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. +- Exception reporting must work before and after application construction. Signal handlers are installed after the + application factory returns; do not claim that this wrapper handles pre-construction signals. 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. -- Crash reporting transports only bounded diagnostic text and a semantic result from the owned child. Failure to render - or save the fallback report must not spawn another supervisor, mutate application state, or replace the original exit - status. +- Shared crash status is a synchronized Boolean plus the child's semantic exit result; diagnostic text is written to + a file and may include retained logs plus a traceback. Do not describe the complete crash file as size-bounded by + the Boolean channel. Redaction and crash-write failure are separate from application-exit correctness. +- Fallback presentation runs in the parent after a nonzero child result and does not rerun normal application + startup. Preserve the original result when evolving error-reporting failures rather than adding another + supervisor. - 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. + `tests/test_application_process.py` and `tests/test_interface.py` are the contract anchors. diff --git a/Furious/Widget/AGENTS.md b/Furious/Widget/AGENTS.md index d6060ed..9bb65df 100644 --- a/Furious/Widget/AGENTS.md +++ b/Furious/Widget/AGENTS.md @@ -1,6 +1,7 @@ # Reusable widget guidance -Inherit the root, package, and Qt guides. This scope covers reusable controls and model/view adapters below page +Inherit the root and package guides; consult `Furious/Qt/AGENTS.md` for shared lifetime/presentation contracts. This +scope covers reusable controls and model/view adapters below page composition; it does not own application workflows. ## Presentation and identity @@ -25,10 +26,14 @@ composition; it does not own application workflows. - 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. -- Model notifications describe the smallest real source mutation. Never use a reset or full repaint to hide incorrect - proxy/source mapping, stale indexes, or missing stable-identity restoration after insert, delete, move, filter, or - sort. -- 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. +- Model notifications describe the real source mutation. Structural replacement may legitimately use a model reset; + metadata-only test results should update the exact cell. Do not use resets/full repaints to mask broken mapping or + missing identity restoration. Test selected identities and the current keyboard index independently. +- Endpoint lookup belongs to `EndpointInfoService`; the map renders validated results and has a no-WebEngine + fallback. Optional WebEngine import failure must not prevent importing the widget/package, and hidden presentation + must not retarget a queued lookup. +- 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. Start with `tests/test_qt_interactions.py`, + `tests/test_profile_test_jobs.py`, and `tests/test_endpoint_info.py`. diff --git a/Furious/Window/AGENTS.md b/Furious/Window/AGENTS.md index 2749101..c44181b 100644 --- a/Furious/Window/AGENTS.md +++ b/Furious/Window/AGENTS.md @@ -1,6 +1,7 @@ # Window and page guidance -Inherit the root, package, Qt, widget, controller, and service guides. This scope owns persistent page composition and +Inherit the root and package guides. Consult Qt/Widget for presentation and Controllers/Service for shared owners. +This scope owns persistent page composition and top-level presentation, not shared domain state. ## Composition and shared state @@ -25,15 +26,23 @@ top-level presentation, not shared domain state. - A page that creates a service must make its process-lifetime or page-lifetime ownership explicit and expose one cleanup path through the containing window/application. Moving a service between pages must not duplicate schedules, histories, requests, or controller connections during the transition. -- 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. +- One-shot editors/prompts use managed transient dialogs and weak compiled-safe continuations. Reusable text/editor + windows and retained settings dialogs need an explicit owner and reopen policy. A settings label or Qt parent does + not determine lifetime: check the actual base class and close/accept/reject path before changing deletion policy. - 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. +- QR export captures capped independent profile snapshots before deferred work. Incremental generation is owned by + the result window and stops on close; a malformed item cannot retarget or invalidate completed tabs. Resizing + scales the cached module image at integer factors with its quiet zone, rather than regenerating or smoothing + secret-bearing QR content. Reuse plugin export semantics and never log the encoded URI. +- Log views keep per-filter cursors and catch up on visibility; metrics pages derive series from shared raw history. + Switching pages, ranges, or filters must not reset collection or create a second history. ## 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. +- 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. Relevant anchors include `tests/test_ui_behavior.py`, + `tests/test_qr_export_scalability.py`, `tests/test_metrics_behavior.py`, and `tests/test_main_window_geometry.py`. diff --git a/Icons/AGENTS.md b/Icons/AGENTS.md index 7b4a95b..6df6c49 100644 --- a/Icons/AGENTS.md +++ b/Icons/AGENTS.md @@ -7,10 +7,14 @@ resource-manifest contract; it does not govern general UI layout. remote resources, embedded rasters, editor metadata, or hard-coded page backgrounds. - Follow the established monochrome/current-color convention so the shared `AppQ*` presentation layer can tint icons. Add a theme-specific variant only when semantic tinting cannot express the design, and do not rely on color alone. -- Preserve license/provenance and the `Resources.qrc` alias contract. Any add, removal, rename, or alias change updates all - consumers and the manifest, then regenerates `Furious/Frozenlib/AppResources.py` with the compatible PySide6 resource - compiler. Never hand-edit generated resource code. +- Preserve license/provenance and the `Resources.qrc` alias contract. Any add, removal, rename, or alias change + updates all consumers and the manifest, then regenerates `Furious/Frozenlib/AppResources.py` with the selected + environment's `pyside6-rcc Resources.qrc -o Furious/Frozenlib/AppResources.py`. Never hand-edit generated resource + code; inspect compiler-version churn separately from the intended alias/asset change. - Treat the alias as the application-facing identity and the source path as an implementation detail. Search both before replacement so an apparently unused file is not removed while still generated or consumed through an alias. -- Verify alias uniqueness and source/package resolution, then inspect the actual control or tray use under both themes, - high DPI, relevant sizes, disabled/selected states, and platform packaging where applicable. +- Verify alias uniqueness and source/package resolution, then inspect the actual control or tray use under both + themes, high DPI, relevant sizes, disabled/selected states, and platform packaging where applicable. Deployment + icons also have direct filesystem consumers in `Deploy.py`; a resource alias search alone cannot prove a PNG is + unused. Revalidate this guide against `Resources.qrc`, `Furious/Qt/QtGui.py`, and deployment consumers when asset + policy changes. diff --git a/tests/AGENTS.md b/tests/AGENTS.md index b295298..590e838 100644 --- a/tests/AGENTS.md +++ b/tests/AGENTS.md @@ -18,9 +18,10 @@ and test-tier selection; test convenience never weakens a production invariant. ## Test the contract -- Assert public semantic behavior and architectural invariants, not private coordinates, incidental call order, or one - implementation's cache. Cover success, invalid input, timeout/cancel, stale/partial completion, rollback, cleanup, and - compatible persisted input where applicable. +- Assert semantic behavior and architectural invariants, not private coordinates or incidental call order. Internal + counters/registries are valid evidence when ownership, reclamation, or complexity is the contract; pair them with + an observable result instead of treating every implementation detail as forbidden. Cover success, invalid input, + timeout/cancel, stale/partial completion, rollback, cleanup, and compatible persisted input where applicable. - For staged changes, fail immediately before commit and prove live plus persisted state is unchanged. Test a post-commit side-effect failure separately. Keep persisted-profile assertions distinct from runtime-copy output. - Use stable profile/subscription identities in reconciliation and async tests. Exercise supersession, removal/reorder, @@ -33,11 +34,19 @@ and test-tier selection; test convenience never weakens a production invariant. ## Tiers and maintenance -- Run the narrow module first, then the affected tier documented in `tests/README.md`. The release-confidence tier is +- Use `python -m unittest tests. -v` from the root for focused work and `python -m unittest discover -s + tests -v` for full source-suite discovery (opt-in tests still skip). The runner is unittest, not pytest. Run the + narrow module first, then the affected tier documented in `tests/README.md`. The release-confidence tier is explicitly opt-in with `FURIOUS_VERY_HEAVY_TESTS=1`; packaged/manual smoke work uses disposable environments. +- Source-only tests and an offscreen platform do not prove a packaged Qt runtime. Compiler-sensitive changes need + the relevant native lifecycle module and a separate compiled probe; report skipped or unavailable targets + explicitly. The release workflow currently builds/checks artifacts without running this source behavioral suite. - Benchmarks report scale and latency but are not correctness gates. Keep deterministic scale assertions in normal or stress tests and avoid machine-dependent elapsed-time thresholds unless the test is explicitly diagnostic. - Update `tests/README.md` when coverage ownership, modules, commands, tiers, opt-ins, or environment requirements change. The final unittest status and process exit code are authoritative even when negative paths intentionally log errors. -- Review new tests for production-state mutation, live network dependence, process-name cleanup, unbounded waits, shared - mutable fixtures, order dependence, timing-only assertions, and storage assertions where runtime output is the contract. +- Review new tests for production-state mutation, live network dependence, process-name cleanup, unbounded waits, + shared mutable fixtures, order dependence, timing-only assertions, and storage assertions where runtime output is + the contract. For guidance-only changes, verify path preservation, changed-file scope, referenced commands/tests, + and contradictory claims; run existing behavior tests only to resolve architecture uncertainty rather than adding + tests of prose.