mirror of
https://github.com/LorenEteval/Furious.git
synced 2026-10-12 17:28:35 +03:00
Improve repository guidance
Signed-off-by: Loren Eteval <loren.eteval@proton.me>
This commit is contained in:
@@ -37,6 +37,10 @@ Read `.github/workflows/deploy-pypi.yml` with `tests/README.md`; paths are relat
|
||||
Audit evaluated generic bases and import-time standard-library APIs as well as syntax and wheel availability.
|
||||
`from __future__ import annotations` does not defer class-base evaluation; test cold imports on a claimed minimum
|
||||
interpreter before treating metadata classifiers or a newer CI row as evidence for that minimum.
|
||||
- Windows Nuitka resource embedding is configured by `Deploy.py` through `NUITKA_RESOURCE_MODE=coff_obj`. Keep
|
||||
that environment on the compiler subprocess, including alternate compiler paths. Inspect the generated build
|
||||
report for the selected compiler and resource mode; a compiler executable on PATH does not prove it was used.
|
||||
Validate startup and shutdown with ordinary flags as well as any diagnostic build before changing this policy.
|
||||
- Coordinate explicit native pins across manifests, source-build/wheel-install steps, and API assertions. When native
|
||||
provenance is exported, compare it with the intended upstream revision as well as distribution metadata.
|
||||
Constructing and closing an engine validates a different boundary from starting a privileged TUN interface.
|
||||
|
||||
@@ -3,15 +3,17 @@
|
||||
## Learn before changing
|
||||
|
||||
- Treat the checked-out tree, tests, build configuration, and verified runtime behavior as the immediate source of
|
||||
truth.
|
||||
Existing guidance is a maintained model, not an authority that can make itself true.
|
||||
truth. Separate a required invariant, an observed implementation, and executed verification; a guide or test
|
||||
name alone proves none of them. Existing guidance is a maintained model, not an authority that can make
|
||||
itself true.
|
||||
- If `.codegraph/` exists, use CodeGraph before broad text searches for structural questions; use `rg` for exact
|
||||
follow-up. Inspect callers, tests, persisted formats, platform branches, and packaging consumers before changing a
|
||||
contract.
|
||||
For nested checkouts or snapshots, confirm that returned source paths belong to the target tree. A placeholder
|
||||
index directory or an enclosing repository's graph does not establish coverage; inspect local files when needed.
|
||||
- For substantial work, use this loop: understand the intended owner and invariant; form a hypothesis; trace the real
|
||||
call/runtime path; implement at the owning boundary; test real behavior; then re-evaluate the architectural model.
|
||||
- For substantial work, identify the authority, acquired resources, commit point, and failure owner before editing.
|
||||
Trace entry through publication and cleanup, including who retries failed release; then test the owning boundary
|
||||
and re-evaluate the model. An async entry point, terminal signal, or cleanup registration is not the whole path.
|
||||
- When guidance says A and code appears to do B, inspect the call path and tests. Decide whether B is intentional
|
||||
evolution, compatibility debt, or a bug; preserve the intended invariant and update either code or the narrowest
|
||||
applicable guidance. Never resolve the contradiction by deleting the scoped guidance file. Do not encode speculation,
|
||||
@@ -41,8 +43,8 @@
|
||||
## Operating model
|
||||
|
||||
- Furious is a cross-platform PySide6 desktop client. Entrypoints reach `Furious.__main__`; a parent process translates
|
||||
child exit/crash results, while the Qt application performs singleton election, composes process-lifetime owners,
|
||||
runs the event loop, and unwinds acquired resources in reverse order.
|
||||
child exit/crash results and enforces bounded shutdown, while the Qt application performs singleton election,
|
||||
composes process-lifetime owners, runs the event loop, and unwinds acquired resources in reverse order.
|
||||
- Read the packages as cooperating responsibilities rather than a strict stack: `Interface` and `Models` define
|
||||
dependency-light contracts/domain values; `Repository` persists them; `Plugins` defines backend/extension contracts;
|
||||
bundled `Backends` and `Extensions` implement those contracts; `Service` owns workflows and temporary resources;
|
||||
@@ -66,9 +68,8 @@
|
||||
copies unless an API deliberately mutates storage. A failed pre-commit stage leaves persistence unchanged; a failed
|
||||
post-commit side effect is reported without pretending the commit rolled back. Identify the unit of commit:
|
||||
cancellation of a batched operation may preserve completed batches rather than roll back the entire command.
|
||||
- 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.
|
||||
- Use stable domain identity, not table rows, proxy indexes, display text, or object position. Async results also
|
||||
prove that the operation and target document are still current before mutation; equal identity is not freshness.
|
||||
- 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.
|
||||
@@ -161,6 +162,6 @@
|
||||
path as well as its successful caller; a test name is an investigation anchor, not proof of unexercised behavior.
|
||||
Keep run-specific counts, versions, diagnostic experiments, and defect inventories in the work report; guidance
|
||||
retains the required invariant and a source/test anchor. Do not repeatedly append symptoms to a local guide.
|
||||
Separate an implemented safeguard from a required but unfulfilled contract. Documentation must neither claim
|
||||
a missing safeguard exists nor redefine the defect as intended behavior merely because its tests currently pass.
|
||||
During guidance-only work, report defects separately instead of changing production code to satisfy the prose.
|
||||
Complete the fresh-reader and adversarial review before handoff, then verify every original guide path and
|
||||
unrelated file remains intact. An accurate requirement must not be weakened to bless a failing implementation.
|
||||
|
||||
+3
-4
@@ -9,10 +9,9 @@ Read `Furious/__init__.py` with `tests/test_public_api.py`; paths are relative t
|
||||
|
||||
- `Application` is the composition root. Elsewhere depend on the narrowest model, repository, service, controller, or
|
||||
plugin capability that owns the decision; do not add a second cache or state path to avoid an existing boundary.
|
||||
- Domain shape, identity, and pure configuration transformations belong in `Models`; restoration, migration, ordering, and
|
||||
durable mutation in `Repository`; temporary work/external resources in `Service`; shared transitions in
|
||||
`Controllers`; backend variation in plugin contracts/implementations; host mutation in `Frozenlib` or a runtime;
|
||||
presentation in `Qt`, `Widget`, `Window`, or `Actions`.
|
||||
- Use the root responsibility map to locate an owner, then trace the actual caller before moving work. Construction
|
||||
beneath a page, a package re-export, or a forwarding property does not transfer the underlying state authority.
|
||||
A move must preserve its acquisition, publication and cleanup paths, including partial application composition.
|
||||
- `Interface` and `Models` stay dependency-light and must not import UI, controllers, services, repositories, or concrete
|
||||
backends. Backend/runtime modules remain importable without constructing editors or the application.
|
||||
- Package `__init__.py` files are curated compatibility surfaces, not mirrors. Import-time settings registration and
|
||||
|
||||
@@ -20,7 +20,8 @@ Read `Furious/Actions/Import.py` with `tests/test_qt_interactions.py`; paths are
|
||||
selection or reconnect command; user-defined labels remain untranslated.
|
||||
- Existing import actions still combine capture/file/clipboard presentation with incremental repository insertion. Treat
|
||||
that as a compatibility path, not a service template. Reuse plugin protocol parsing, construct a complete valid result
|
||||
before each mutation, and keep batched GUI work cancellable and bounded per event-loop turn.
|
||||
before each mutation, and yield between cancellable batches. Batch admission bounds do not preempt an individual
|
||||
synchronous parser, file read or QR decoder; evaluate that work separately before claiming a responsive command.
|
||||
A surviving main window does not authorize a file import after its initiating action dies during selection.
|
||||
Apply the shared Qt continuation rule before reading/parsing the chosen file; the modal cases in `test_qt_lifetime.py`
|
||||
exercise the action boundary separately from the window boundary.
|
||||
|
||||
@@ -20,8 +20,9 @@ relative to this source tree's root.
|
||||
`exit()` announces shutdown to `AppMainProcess` before requesting controller cleanup. Failed connection cleanup
|
||||
is retried by one application-owned single-shot timer while Qt delivery remains active; successful cleanup requests
|
||||
Qt termination. Repeated exit requests do not reset the deadline or requested result. Action/window/session handlers
|
||||
do not run the application cleanup stack directly. The existing parent enforces the ten-second deadline even if
|
||||
a synchronous cleanup stage blocks Qt, then forces application exit. Final cleanup announces shutdown too, covering
|
||||
do not run the application cleanup stack directly. The existing parent enforces its bounded shutdown deadline
|
||||
even if a synchronous cleanup stage blocks Qt, then forces application exit. Final cleanup announces
|
||||
shutdown too, covering
|
||||
run-loop failure and direct Qt quit. This policy requires the supervised entry point; constructing an application
|
||||
alone does not create a watchdog. Forced exit can interrupt unfinished persistence and host restoration.
|
||||
`tests/test_architecture_refactors.py` exercises the real quit/event-loop boundary alongside cleanup ordering.
|
||||
@@ -29,9 +30,10 @@ relative to this source tree's root.
|
||||
cleanup stack releases completed stages; it cannot discover half-built controllers, UI, logging handlers, or
|
||||
native listeners. Keep each successful sub-acquisition reachable by the stage's failure cleanup before beginning
|
||||
the next fallible constructor; assigning several constructed owners together does not provide this guarantee.
|
||||
Restore logging configuration as well as closing handlers. Connection retries happen before the cleanup stack;
|
||||
the consumed final cleanup stage does not retry arbitrary callbacks. Preserve incomplete resource ownership until
|
||||
graceful release or forced process exit, and keep cleanup failures visible.
|
||||
Restore logging configuration as well as closing handlers. Keep the retry chain explicit: retained service lease,
|
||||
controller shutdown result, application retry timer, then the parent deadline. The final cleanup stack consumes
|
||||
arbitrary callbacks once; registering a callback there does not add retry. Preserve unresolved ownership and
|
||||
diagnostics until graceful release or forced process exit.
|
||||
For resource-owning controllers, schedule native deletion only after successful shutdown. UI deletion and
|
||||
workflow draining are separate stages; trace both rather than assuming `deleteLater()` waits for resources.
|
||||
Review cooperative pool drains separately from the cleanup stack's ordering guarantees. The application pool's
|
||||
|
||||
@@ -14,8 +14,10 @@ tree's root.
|
||||
independent runtime copy; failed preparation must not mutate the stored profile. The registry passes the
|
||||
supplied connection document through to the factory, so caller isolation is part of the contract. Inspect both
|
||||
normal connection preparation and temporary probes when changing a mutating factory.
|
||||
- Structured editors are partial projections. Loading is observational except for a narrow documented migration;
|
||||
untouched save preserves unknown fields/values and absent defaults. Editing one represented leaf preserves unknown
|
||||
- Profile editors are partial projections. Loading is observational except for a narrow documented migration;
|
||||
untouched save preserves unknown fields/values and absent defaults. Backend tools with deliberate live mutation,
|
||||
such as Xray routing-rule editing, must expose that commit policy instead of implying reject-to-rollback
|
||||
behavior. Editing one represented leaf preserves unknown
|
||||
siblings and unrelated branches. URI export represents the codec's supported projection, not a lossless backup
|
||||
of every document field; exporting must leave the source document unchanged.
|
||||
- Malformed external input returns controlled validation with backend context. Do not create a plausible but different
|
||||
|
||||
@@ -51,7 +51,9 @@ source tree's root.
|
||||
`tests/test_external_core.py` and `tests/test_backend_editor_contract.py`. Exercise a child that remains alive
|
||||
after escalation and readers/watchers that outlast their joins. A failed final reap is a cleanup failure to report;
|
||||
clearing the runtime's process/thread references must not be used as evidence that those resources exited.
|
||||
Retain an independent reference in failure tests so an empty runtime field cannot make the test pass. Direct-child
|
||||
exit also does not prove that descendants closed inherited pipes. Review `Process.py` and
|
||||
Retain independent references to the process and I/O threads in failure tests so clearing runtime fields cannot
|
||||
make them pass. A stopped process with a live reader is still incomplete disposal; retry must finish release
|
||||
without relaunching or publishing a second exit. Direct-child exit does not prove descendants closed
|
||||
inherited pipes. Review `Process.py` and
|
||||
`Furious/Service/RuntimeLease.py` together: incomplete shutdown must preserve observable outstanding resources
|
||||
and an owner able to finish cleanup, without broad process-name cleanup.
|
||||
|
||||
@@ -29,8 +29,9 @@ source tree's root.
|
||||
- Capability absence is deliberate: this factory supplies neither native TUN nor a statistics provider. Shared UI
|
||||
must not infer either from Hysteria 2 support. Download preparation replaces the HTTP listener and removes SOCKS
|
||||
on a copy; test traffic must use its owned endpoint without applying ordinary connection host effects.
|
||||
Listener readiness does not validate the prepared ACL/MMDB contents. Test file preparation and native startup
|
||||
failure separately instead of treating TCP acceptance as acceptance of every launch input.
|
||||
Listener readiness observes the local endpoint; inspect ACL/MMDB preparation and native startup failure
|
||||
separately. A valid client document or accepted
|
||||
TCP connection does not validate those extra file inputs.
|
||||
- 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. Use `tests/test_hysteria1_protocol.py`,
|
||||
|
||||
@@ -46,10 +46,10 @@ this source tree's root.
|
||||
routing presentation and runtime preparation; a stored routing preference is not evidence of backend support.
|
||||
- Verify nested sibling/default preservation, known and unknown values, obfuscation switching, URI/document
|
||||
projection preservation, every native/application-TUN and resolution case, probe stripping, readiness/exit cleanup,
|
||||
statistics cancellation, and repeated transient editor/settings-dialog destruction. Check the configured
|
||||
statistics target independently from the HTTP proxy readiness endpoint: the former queries the server API,
|
||||
while the latter only observes the local client listener. A monitor target is captured execution data;
|
||||
current UI credentials or an edited profile must not silently replace a running connection's statistics target.
|
||||
statistics cancellation, and repeated transient editor/settings-dialog destruction. Change the live profile or
|
||||
configured statistics credentials after launch in tests: the monitor must keep that runtime's captured target,
|
||||
while a later connection can use the new settings. Test missing-client zero counters separately from query
|
||||
failure.
|
||||
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
|
||||
|
||||
@@ -38,9 +38,9 @@ source tree's root.
|
||||
download path and does not inherit runtime staging or checksum guarantees. Hash jobs receive copied bytes
|
||||
and return through the updater's Qt-thread boundary; closing the updater must release request and hash-callback
|
||||
contexts independently, including native destruction without a normal reply completion.
|
||||
Checksum workers own copied bytes and opaque job identity, not a download callback or transient Qt receiver.
|
||||
Resolve result context on the updater's Qt thread and discard it at shutdown; a completed hash is not permission
|
||||
to revive a retired download. `tests/test_xray_asset_download.py` covers the blocked-worker destruction case.
|
||||
Workers retain copied bytes and job identity, not a download callback or transient receiver. Verify digest
|
||||
mismatch, short write and failed `QSaveFile.commit()` without losing prior bytes, plus blocked-worker destruction
|
||||
in `tests/test_xray_asset_download.py`. Late hash completion must not revive a retired download.
|
||||
- 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.
|
||||
Trace the selected repository routing document separately from the connection's routing branch and prepared
|
||||
|
||||
@@ -64,6 +64,8 @@ source tree's root.
|
||||
Pending asynchronous cleanup stays `Disconnecting`, with runtime ownership in the service. Reconnect waits for
|
||||
successful release; a genuine cleanup failure returns to usable UI without admitting replacement resources.
|
||||
Shutdown publishes its result only after this stop operation finishes and preserves the startup preference.
|
||||
An unsuccessful result must remain retryable by the application; the controller does not own the final process
|
||||
deadline. Test a second shutdown against retained leases, not just a second call after successful cleanup.
|
||||
`tests/test_sing_tun.py` covers delayed authorization, cancellation, reconnect and shutdown with real Qt delivery.
|
||||
- System Proxy configuration is best effort. Its helper logs host failures; an explicit False return does not roll
|
||||
back an otherwise usable committed runtime or prevent Connected. Preserve exception-path recovery separately.
|
||||
|
||||
@@ -13,9 +13,9 @@ relative to this source tree's root.
|
||||
disposal if execution never starts. Failed launch-factory construction must dispose resources already acquired
|
||||
before propagating the failure, because no service has received ownership yet. 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.
|
||||
- Preserve the Interface execution/readiness distinction at the process boundary. If a child exits before its
|
||||
queued terminal event reaches the service, readiness polling must retain the typed failure rather than replace
|
||||
it with a timeout. Exercise this ordering with the real Qt delivery boundary and an owned test child or runtime.
|
||||
- Required cleanup covers the exact child, process handle, monitor/drain timers, queues, callbacks, and feeder
|
||||
resources. Stop must bound waits, escalate only the owned child, and remain safe after partial start or repetition.
|
||||
Execution exit, terminal-event delivery, and monitor/transport disposal need separate assertions; success at one
|
||||
|
||||
@@ -51,5 +51,7 @@ tree's root.
|
||||
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. Check actual artifact contents, including nested Markdown exclusions,
|
||||
rather than only the presence of package-data patterns. Successful inclusion does not prove runtime write access or
|
||||
optional WebEngine availability. Revalidate provenance/network claims when an asset provider or loader changes.
|
||||
rather than only the presence of package-data patterns. Standalone probes can use broader data inclusion than
|
||||
releases; Markdown in a probe does not prove a release leak, and a source exclusion pattern does not prove the
|
||||
built artifact is clean. Successful inclusion does not prove write access or optional WebEngine
|
||||
availability. Revalidate provenance/network claims when an asset provider or loader changes.
|
||||
|
||||
@@ -24,8 +24,6 @@ relative to this source tree's root.
|
||||
- Worker safety is a property of the whole preparation path. Standard decoders opt in, but the selected protocol
|
||||
handlers must also opt in after their shared state, caches, and Qt use are audited. Preserve the GUI compatibility
|
||||
fallback for unclassified capabilities; a safe envelope decoder cannot authorize an unsafe downstream parser.
|
||||
Decoding and per-item import retain separate failure counts: a matched envelope may contain rejected protocols.
|
||||
Preserve those outcomes through reconciliation so partial acceptance is not mistaken for an unchanged remote set.
|
||||
- Decoder output is descriptive, not a repository transaction. Supplied names and upstream IDs are input to
|
||||
profile construction, not permission to overwrite local identity or grant remote ownership. It cannot mutate
|
||||
a group, cancel tests, reconnect, or publish UI state; those decisions remain at the import/manager commit
|
||||
@@ -36,7 +34,9 @@ relative to this source tree's root.
|
||||
recognized-empty, wholly unsupported, mixed-validity, and duplicate payloads separately so decoder matching
|
||||
is not confused with successful import or authorization to clear an existing group. The standard share-link
|
||||
decoder treats blank/comment-only content as a mismatch; an empty result from a different decoder needs its
|
||||
own import/reconciliation policy, not an assumption borrowed from this format.
|
||||
own import/reconciliation policy, not an assumption borrowed from this format. Preserve recognized item count,
|
||||
accepted profiles and rejected items separately through the manager: a successful envelope parse cannot decide
|
||||
whether a partial or empty remote result should replace stored profiles.
|
||||
- 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
|
||||
|
||||
Vendored
+2
@@ -60,6 +60,8 @@ tree's root.
|
||||
diff, then run it again to check stability. Idempotent output proves generator stability, not translation quality
|
||||
or runtime reachability; verify the changed keys through their controls or lookup paths. Collision and write
|
||||
failures are logged rather than guaranteed to produce a nonzero process exit; exit status alone is not validation.
|
||||
Compare extracted membership and curated values separately: a stable second run can repeat a destructive first
|
||||
run. Preserve the original catalog for comparison before invoking an intentional update.
|
||||
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
|
||||
|
||||
@@ -53,7 +53,8 @@ Read `Furious/Frozenlib/AppSettings.py` with `tests/test_frozenlib.py`; paths ar
|
||||
cancellation and reaping. `LinuxExecutePrivilegedScript` preserves the synchronous Boolean/diagnostic contract
|
||||
through that launcher. The launcher uses the effective UID to skip pkexec for root; callers do not select
|
||||
elevation themselves. Sing-tun retains its independent helper lifecycle.
|
||||
Authorization has no application deadline. `tests/test_frozenlib.py` covers launch arguments, diagnostics,
|
||||
Authorization has no separate startup timeout. This does not suspend the outer application shutdown deadline
|
||||
or prove host recovery after forced exit. `tests/test_frozenlib.py` covers launch arguments, diagnostics,
|
||||
interruption and child release; `tests/test_sing_tun_linux_host.py` covers the retained sing-tun session.
|
||||
- `SingTUNRouting.py` owns sing-tun's Linux prerequisites, routing identifiers, command construction, privileged
|
||||
helper processes/scripts, interface/DNS operations and exact cleanup checks. It remains independent of tun2socks'
|
||||
@@ -64,8 +65,9 @@ Read `Furious/Frozenlib/AppSettings.py` with `tests/test_frozenlib.py`; paths ar
|
||||
stdin runs its exact cleanup, including on parent exit. It accepts no executable commands from the application.
|
||||
Record successful rule additions in the helper for partial rollback. Kernel JSON read-back is a verification and
|
||||
recovery boundary, not the source of normal teardown commands; its field spellings differ from CLI selectors.
|
||||
PolicyKit authorization deliberately has no deadline, matching tun2socks. Keep it distinct from bounded host
|
||||
reads and explicit cancellation/reaping waits; elapsed time alone must not expire a pending password request.
|
||||
Keep a pending PolicyKit request distinct from bounded host reads and cancellation/reaping waits. Ordinary
|
||||
startup does not expire the password request merely because a readiness interval elapsed; application termination
|
||||
can still interrupt the helper lifecycle. Verify exact helper release separately from application-child exit.
|
||||
- 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
|
||||
|
||||
@@ -15,8 +15,9 @@ Read `Furious/Interface/Runtime.py` with `tests/test_interface.py`; paths are re
|
||||
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
|
||||
it. It specifies zero-argument start, passive liveness, typed terminal events, and stop/dispose obligations;
|
||||
implementations provide the resource behavior. Preparation, serialization, readiness, and startup
|
||||
transactions belong outside this contract. Bind its
|
||||
event sink once before start; the callback may originate on a worker thread, so the receiving owner supplies explicit
|
||||
thread-safe delivery. Concrete runtimes own once-only terminal publication; the base publisher forwards events and
|
||||
does not deduplicate them. Process/child terminology belongs only to implementations that own one. A weak
|
||||
@@ -49,7 +50,9 @@ Read `Furious/Interface/Runtime.py` with `tests/test_interface.py`; paths are re
|
||||
`cleanupPending` separately reports asynchronous resource release. While true, callers retain the runtime and
|
||||
poll stop/dispose from their owning thread; pending work is not a failed stop or a disposed runtime. False alone
|
||||
is not release proof: exceptions and actual resource/liveness checks still apply. The default is false for
|
||||
synchronous implementations; sing-tun's Linux restoration and the lease tests anchor the deferred case.
|
||||
synchronous implementations; sing-tun's Linux restoration and the lease tests anchor the deferred case. The
|
||||
property does not schedule polling. Inspect the retaining caller and its retry path when adding a deferred
|
||||
runtime.
|
||||
- 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
|
||||
|
||||
@@ -34,8 +34,9 @@ root.
|
||||
- Treat serialized and plugin-provided mappings as untrusted values. Normalize only documented compatibility aliases,
|
||||
retain unknown forward-compatible fields, and keep construction diagnostics available without mutating repositories
|
||||
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.
|
||||
- `ensureProfile()` normalizes rather than clones: metadata arguments update an existing profile. Include this
|
||||
aliasing behavior when testing callers that accept either a profile or a bare connection; testing only the latter
|
||||
can conceal mutation of live metadata during preparation.
|
||||
- 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
|
||||
|
||||
@@ -13,8 +13,9 @@ tree's root.
|
||||
- The registry normalizes and validates a plugin's complete contribution before changing indexes. Initialization
|
||||
runs with the contribution indexed; if it fails, shutdown is attempted and those indexes are removed. This is
|
||||
rollback of registry publication, not a transaction over arbitrary plugin side effects. Plugins must clean their
|
||||
own partial acquisitions even when initialization fails. Duplicate IDs/schemes and invalid versions/descriptors
|
||||
must leave existing providers intact.
|
||||
own partial acquisitions even when initialization fails. Admission requires the API version declared by the host,
|
||||
not a best-effort interpretation of older shapes. Duplicate IDs/schemes and invalid versions/descriptors must
|
||||
leave existing providers intact.
|
||||
- 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
|
||||
@@ -29,8 +30,10 @@ tree's root.
|
||||
## Ownership and compatibility
|
||||
|
||||
- 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.
|
||||
callers. Capabilities may retain explicitly owned reusable services with shutdown obligations. Registry shutdown
|
||||
marks the registry closed and invokes initialized plugins in reverse order once; it diagnoses failures without
|
||||
automatically retrying them. A capability needing another cleanup attempt must keep an explicit owner/caller.
|
||||
Do not cache transient UI here or treat the registry as the connection/repository authority.
|
||||
- Separate factory construction, registry result validation, and execution start. A factory owns partial resources
|
||||
until it returns a valid launch; the caller cannot recover an object hidden by construction failure or an invalid
|
||||
result shape. After valid transfer the caller owns that exact runtime even if start raises. Keep failure evidence
|
||||
|
||||
@@ -79,12 +79,11 @@ Use the `manage-qt-pyside6-lifetimes` skill for source lifetime work when availa
|
||||
`singleShotWeakly()` for deferred named-method delivery. A closure/partial that captures the receiver does not
|
||||
substitute for weak dispatch. Bounded dialog-completion closures may intentionally capture context; verify their
|
||||
native destruction/disconnection boundary and both owner-first and sender-first teardown.
|
||||
- Detaching a child ends the shared QObject-tree lifetime assumption. Disconnect the registrations owned by that
|
||||
feature before reparenting, preserve unrelated listeners, and remove default/escape/selection references when the
|
||||
child dies. Signal delivery is also a reentrancy boundary: a listener may delete the sender or its owner before
|
||||
the emitting method resumes. Recheck validity before later native calls; a weak dispatcher protects entry,
|
||||
not the rest of an in-flight method. Workflow owners additionally recheck their generation after delivery. `AppQMessageBox` button reuse and
|
||||
native-destruction regressions exercise both boundaries.
|
||||
- Detaching a child ends the shared QObject-tree lifetime assumption. Retire that feature's registrations before
|
||||
reparenting, preserve unrelated listeners, and remove default/escape/selection references when the child dies.
|
||||
Apply the continuation rule above after signal delivery; validity and workflow generation remain separate checks.
|
||||
`AppQMessageBox` button reuse and native-destruction cases test ownership changes and reentrant delivery
|
||||
together.
|
||||
Controller refreshes, selection callbacks, and setting callbacks can likewise end their initiating control's
|
||||
lifetime before returning. QAction text/check/icon/visibility setters publish `changed` synchronously: stop a
|
||||
translation or presentation sequence if its owner dies, and reject a superseded state snapshot before the next
|
||||
@@ -103,9 +102,10 @@ Use the `manage-qt-pyside6-lifetimes` skill for source lifetime work when availa
|
||||
workflow owner. None replaces the strong owner required while asynchronous UI remains active. For independent
|
||||
sender/receiver trees, test both destruction orders: receiver cleanup must disconnect its edge, and sender cleanup
|
||||
must retire receiver-side tracking without keeping a signal wrapper or sender alive.
|
||||
Replacing a borrowed sender retires the whole registration, including both lifecycle hooks. `connectWeakly()` can
|
||||
collect these opaque handles in a fresh per-connection list for explicit retirement; its ordinary return remains
|
||||
the main Qt connection. Borrowers clear references on either native teardown without stealing a shared Qt owner.
|
||||
Replacing a borrowed sender retires the whole registration, including both lifecycle hooks. `connectWeakly()`
|
||||
collects these opaque handles only when given a fresh empty per-connection list; its ordinary return is just the
|
||||
main connection. Disconnecting that return alone does not retire the independently installed lifecycle
|
||||
hooks. Borrowers clear references on either native teardown without stealing a shared Qt owner.
|
||||
- `AppQAction.callback` is strong by design, so its owner must not outlive the captured receiver; construction alone
|
||||
does not enforce that requirement. An action also owns a submenu supplied without a QWidget parent and schedules
|
||||
its native deletion when the action dies;
|
||||
|
||||
@@ -28,9 +28,9 @@ to this source tree's root.
|
||||
not authorize using a partial collection. Test malformed records inside a valid root as well as malformed
|
||||
roots. Profile and subscription hydration publishes only a complete collection; an invalid record must not
|
||||
expose a partially restored prefix that cleanup can serialize over the original document. The
|
||||
restore-failure guard protects automatic cleanup, not an arbitrary explicit `sync()` call. Do not flush an
|
||||
empty fallback merely to inspect or acknowledge a load failure; test the original persisted bytes through
|
||||
the cleanup path.
|
||||
restore-failure guard protects automatic cleanup, not an arbitrary explicit `sync()` call: explicit server sync
|
||||
writes the current collection and clears that guard. Do not call it merely to inspect or acknowledge a load
|
||||
failure. Test automatic cleanup preservation and intentional replacement as different operations.
|
||||
- Stage fallible decode/migration before live mutation. Subscription reconciliation currently belongs to
|
||||
`Furious/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
|
||||
|
||||
@@ -46,7 +46,8 @@ source tree's root.
|
||||
timers and asynchronous DNS cannot preempt synchronous work. Keep cancellation checks at reentrant stage boundaries
|
||||
before acquiring the next resource, and audit shared route bookkeeping separately from attempt-local leases.
|
||||
Linux tun2socks GUI startup runs its privileged setup script in an attempt-owned `Tun2socksHostPreparation`
|
||||
worker. Its Qt observer has no authorization deadline. Cancellation marks the retained script so late
|
||||
worker. Its Qt observer imposes no startup authorization timeout; the parent-enforced application shutdown
|
||||
deadline remains independent. Cancellation marks the retained script so late
|
||||
authorization cannot begin setup; keep the worker and files owned until the helper returns before runtime
|
||||
disposal or replacement. The synchronous startup compatibility path retains its existing blocking helper.
|
||||
`tests/test_connection_startup_async.py` checks real progress-timer delivery, cancellation ownership and
|
||||
@@ -64,8 +65,9 @@ source tree's root.
|
||||
- For sing-tun, resolve automatic and manual remote exclusions before applying host routing, then require
|
||||
native readiness and checked DNS application before commit. `SingTUNHostPlan` owns only its assigned identifiers
|
||||
and DNS snapshots, independently of legacy `SystemRoutingTable.managedRoutes`; refuse ambiguous recovery and
|
||||
retain ownership for retry. Host preparation/DNS commands run in its owned worker. Linux authorization and its
|
||||
startup observer have no deadline; other readiness checks keep their own deadlines. Linux restoration is polled
|
||||
retain ownership for retry. Host preparation/DNS commands run in its owned worker. Linux authorization has
|
||||
no separate startup
|
||||
timeout; other readiness checks and application shutdown retain their own deadlines. Linux restoration is polled
|
||||
through the manager's stop operation rather than joined on Qt's thread. Synchronous startup remains a compatibility
|
||||
path; synchronous stop callers report incomplete release while asynchronous cleanup is pending.
|
||||
Delegate Linux host operations to
|
||||
@@ -92,7 +94,10 @@ source tree's root.
|
||||
retry and refuses new startup while release remains incomplete. A failed attempt transfers unreleased leases
|
||||
back to that durable owner; deleting the attempt must not abandon them. Independent DNS cleanup still runs.
|
||||
Verify runtime liveness and actual handle/thread release separately from the lease's logical state.
|
||||
Pending cleanup is observed through the runtime contract and is not logged as failure. Stop failures retain the
|
||||
The manager retains failed release; the stop operation polls pending release. Application shutdown retries an
|
||||
unsuccessful controller result while Qt is alive, until success or the outer process deadline. These are separate
|
||||
callers, so test retained ownership and actual retry invocation. Pending cleanup is not logged as failure.
|
||||
Stop failures retain the
|
||||
runtime without immediately retrying via dispose, which could open another authorization request. The stop
|
||||
operation owns its Qt timer; destroyed observers leave their leases with the manager. Retire stop admission before
|
||||
terminal signals, preserve other runtimes' independent cleanup, and reject new startup until release completes.
|
||||
|
||||
@@ -23,7 +23,8 @@ source tree's root.
|
||||
- The parent entry point waits through `waitForExit()` for only the child it created. The child's shutdown signal,
|
||||
exception hook, signal handler, or runner completion arms one monotonic deadline before final cleanup or interpreter
|
||||
finalization. Ordinary operation has no deadline; repeated shutdown notifications cannot extend the grace period.
|
||||
After ten seconds the parent kills and boundedly reaps that exact child, even if Qt or Python's GIL is blocked.
|
||||
At the shutdown deadline the parent kills and boundedly reaps that exact child, even if Qt or Python's GIL is
|
||||
blocked. Keep the duration in the implementation and exercise expiry without a production-length test wait.
|
||||
Keep this watchdog in the existing parent: a timer/thread in the child cannot enforce that contract. Never
|
||||
discover or terminate processes by name, and keep normal/source/packaged entry points equivalent.
|
||||
Forced exit preserves the requested semantic result, so an intentional quit does not open a crash dialog solely
|
||||
@@ -45,6 +46,7 @@ source tree's root.
|
||||
or main-window initialization occurred merely because the fallback has a Qt application. Keep its constructor
|
||||
dependencies in failure-path tests and preserve the original result when evolving reporting failures.
|
||||
- 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
|
||||
cross-platform spawn, exact application-child joining, and absence of manager servers. Verify backend children
|
||||
and elevated helpers separately; an application-child reap cannot establish their release. 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,7 +1,8 @@
|
||||
# Reusable widget guidance
|
||||
|
||||
Inherit the [nearest parent guide](../AGENTS.md). Widgets own controls and model/view adapters, not
|
||||
independent workflows. Domain identity survives sorting and deferred commands; indexes remain model-specific.
|
||||
Inherit the [nearest parent guide](../AGENTS.md). Widgets own controls and model/view adapters. Some create
|
||||
service owners for historical composition; commands and results still go through those services. Domain
|
||||
identity survives sorting and deferred commands; indexes remain model-specific.
|
||||
Read `Furious/Widget/ServerTableView.py` with `tests/test_qt_interactions.py`; paths are relative to this
|
||||
source tree's root.
|
||||
|
||||
|
||||
@@ -59,7 +59,8 @@ Read `Furious/Window/MainWindow.py` with `tests/test_ui_behavior.py`; paths are
|
||||
- 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. Attempted
|
||||
items and successful tabs are separate counts: failures still advance the batch, and an all-failed export closes
|
||||
its empty window. Cancellation preserves already generated tabs while releasing pending snapshots. Resizing
|
||||
its empty window. Cancellation preserves already generated tabs while releasing pending snapshots. The timer
|
||||
yields between items; it cannot interrupt a synchronous plugin export or QR encode already in progress. 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.
|
||||
- Search debounce belongs to the persistent page: clear/submit cancels pending work, hide stops it, and show applies
|
||||
|
||||
+3
-3
@@ -35,6 +35,6 @@ Read `Resources.qrc` with `tests/test_public_api.py`; paths are relative to this
|
||||
- Deployment icons have direct filesystem consumers in `Deploy.py` outside the Qt resource namespace. Check those
|
||||
installer/application inputs separately from aliases before removing a PNG. Verify control/tray rendering under
|
||||
both themes, high DPI, relevant sizes, and disabled/selected states; resource generation does not prove themed
|
||||
rendering or inclusion in an installer. Resource generation validates the manifest's input relationship, while
|
||||
consumer rendering validates meaning and visibility; neither proves the other. Keep asset-only checks separate
|
||||
from changes to the action's lifetime or command target.
|
||||
rendering or inclusion in an installer. A read-only manifest audit should check every input and full alias
|
||||
without regenerating `AppResources.py`; regeneration is required when resource inputs actually change. Keep
|
||||
resource presence, consumer rendering, and action lifetime/target assertions separate.
|
||||
|
||||
@@ -72,6 +72,9 @@ Read `tests/support.py` with `tests/README.md`; paths are relative to this sourc
|
||||
Validate an exposed private callback-protection counter with a bounded compiled direct-connection control before
|
||||
treating zero growth as a result. Include the harness configuration and actual package data in standalone probes;
|
||||
import success without `tests/fixtures/offscreen.json` does not establish a runnable isolated fixture.
|
||||
Use `tests/fixtures/shutdown_probe.py` for the outer deadline and cleanup retry contract; the editor lifetime
|
||||
fixture exercises a different boundary. A traced or symbol-enabled executable cannot stand in for the ordinary
|
||||
probe. Record the actual compiler/resource mode and independently assert child reaping and semantic exit status.
|
||||
- Separate deterministic correctness/scale assertions from performance measurements. Opt-in stress tests may gate
|
||||
relative scaling or resource bounds; document the measured contract and environment rather than treating one
|
||||
machine's absolute timing as a portable product requirement.
|
||||
|
||||
Reference in New Issue
Block a user