mirror of
https://github.com/LorenEteval/Furious.git
synced 2026-09-22 15:04:34 +03:00
Align repository guidance with architecture
Signed-off-by: Loren Eteval <loren.eteval@proton.me>
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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 <files>`, then `python -m black --check
|
||||
<files>`; `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.
|
||||
|
||||
+11
-5
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
+18
-12
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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`.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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`.
|
||||
|
||||
+10
-6
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
Vendored
+16
-9
@@ -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 <language>` 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 <language>` 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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
+24
-12
@@ -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.
|
||||
|
||||
+18
-8
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
+37
-20
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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`.
|
||||
|
||||
@@ -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`.
|
||||
|
||||
+9
-5
@@ -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.
|
||||
|
||||
+15
-6
@@ -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.<module> -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.
|
||||
|
||||
Reference in New Issue
Block a user