Align scoped guidance with architecture

Signed-off-by: Loren Eteval <loren.eteval@proton.me>
This commit is contained in:
Loren Eteval
2026-09-09 01:28:46 +08:00
parent c8110ab225
commit 994602c889
27 changed files with 125 additions and 92 deletions
+2 -1
View File
@@ -35,6 +35,7 @@ exceptions; it does not define the source test suite or imply that every package
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.
`needs` and tag gates rather than assuming a downstream publish job runs on every build. Follow each publication
dependency back to its required artifact checks; upload success alone does not establish release eligibility.
- 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.
+10 -11
View File
@@ -48,7 +48,8 @@
controllers/models; they do not copy connection, routing, System Proxy, TUN, subscription, or test state.
- Treat persisted profiles and plugin documents as input. Prepare runtime, routing, probe, and TUN state on explicit
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.
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.
- Distinguish profile identity, subscription membership, remote synchronization ownership, and execution snapshots.
@@ -98,8 +99,8 @@
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.
geometry, or QObject destruction matters. Prefer semantic state and destroyed/resource counts; use targeted
rendering assertions when pixels are the defect, without relying on whole-window snapshots or arbitrary sleeps.
- Before handoff, review for duplicate authorities, persisted-data mutation during preparation, stale async write-back,
swallowed diagnostics, unowned resources, unbounded external-input caches, plugin-specific branches in shared code,
and source-only assumptions at packaging boundaries.
@@ -112,11 +113,9 @@
- Put a rule at the narrowest scope where it helps future decisions; let child guides specialize rather than repeat
parents. Remove obsolete content inside files, distinguish preferred architecture from compatibility paths, and
preserve every established file path while doing so.
- After significant architectural work, ask what durable fact was learned, whether guidance now misleads, and whether a
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.
- After significant architectural work, re-read the applicable hierarchy as a fresh agent: can it identify the
owner, invariant, failure boundary, and relevant tests without relying on conversation history? Challenge rules
likely to become stale, circular references, and wording that freezes incidental structure.
- Distinguish observed behavior from design requirements and name tests/consumers that can challenge a local rule.
A known limitation is not a desired invariant. During guidance-only work, report code defects separately instead
of changing production code to satisfy the prose.
+3 -1
View File
@@ -38,7 +38,9 @@ domain, persistence, orchestration, platform integration, and presentation; nest
- 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.
deliberately separating those responsibilities. Some shared managers are currently constructed under persistent
widgets/pages. Construction location does not transfer workflow authority to every view: moving an owner must
preserve one scheduler, result boundary, and cleanup path. Widgets should not absorb new workflow orchestration.
- Plugin registries index process-lifetime plugins, descriptors, and capabilities. Created editors and active
runtimes transfer to explicit UI/workflow owners. A capability may own a reusable service, such as asset updating,
but that service still needs a cleanup boundary. Built-ins use the public capability contract; existing
+9 -4
View File
@@ -23,10 +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. 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.
- Screen capture and QR decoding currently run synchronously; batching the resulting imports does not make capture
interruptible. If moved to workers, transfer data through an owned GUI-thread continuation without retaining
transient windows. QR export generation belongs to its result window, not a parallel action-owned exporter.
- Small profile imports use the direct bulk path; large imports yield between bounded batches. Preserve captured
input and one operation context until completion/cancellation, reject deferred calls after teardown, and retain
already committed batches when cancellation stops later work. A parser call itself is not preempted by a batch.
- Batch limits bound work between event-loop yields; the minimum progress interval throttles status refreshes at
those boundaries. It is not an independent paint timer. Keep terminal feedback accurate and choose scale policies
from measured responsiveness rather than freezing a batch count into the command contract.
- 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.
+6 -3
View File
@@ -5,13 +5,16 @@ child-process supervisor and the inner application event loop.
- `Furious.__main__` and `AppMainProcess` own the outer process/crash boundary; `DesktopApplication` owns the inner Qt
composition. Keep those responsibilities separate and preserve semantic exit codes and original failure context.
- Startup acquires singleton ownership before composing process-lifetime repositories, plugins, controllers, logging,
host integration, UI, and optional restored connection. Register cleanup as each acquisition succeeds.
- Startup stages begin after singleton election. Plugins are available before repository restoration
interprets persisted profiles; controllers and presentation consume those initialized owners. Register cleanup as
each acquisition succeeds, and preserve these dependencies when changing stage order.
- 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.
- 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.
native listeners. Restore logging configuration as well as closing handlers. Run service shutdown while its
owners remain valid; scheduling `deleteLater()` is not evidence that workers or native resources have finished.
Review cooperative pool drains separately from the cleanup stack's ordering guarantees.
- 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
+6 -5
View File
@@ -1,8 +1,7 @@
# Backend guidance
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.
scope adds rules shared by all bundled proxy backends without making the richest backend the generic default.
## Common backend contract
@@ -13,7 +12,8 @@ backends without making the richest backend the generic default.
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;
untouched save preserves unknown fields/values and absent defaults. Editing one represented leaf preserves unknown
siblings and unrelated branches.
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
profile, and do not log credentials, complete URIs, or documents.
- Configuration/runtime modules stay importable without constructing Qt editors. Plugin registration remains literal
@@ -28,8 +28,9 @@ backends without making the richest backend the generic default.
- 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.
- A runtime owns its exact process/thread/readers/monitors and publishes an actionable start error. Stop/dispose
must be bounded, idempotent, and safe after partial acquisition. Report incomplete reaping explicitly; reaching a
deadline or changing logical execution state does not prove that native resources have exited.
- Runtime factories follow the current plugin contract: fully prepare and return one owned launch whose zero-argument
start is separate from readiness observation. Do not hide readiness waits, Boolean success channels, or controller
policy inside a backend runtime.
+3 -3
View File
@@ -1,8 +1,7 @@
# External Core guidance
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.
the intentionally different direct-subprocess scope for user-selected executables.
## Structured executable boundary
@@ -27,7 +26,8 @@ user-selected executables.
- 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.
executable's remote service. Endpoint metadata does not configure the executable or cause it to open a listener;
users remain responsible for matching that metadata to the executable's own configuration.
- 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
+4 -7
View File
@@ -1,21 +1,18 @@
# Hysteria 1 guidance
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.
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
documents, obfuscation, statistics, realm, or native-TUN semantics merely because the upstream names are related.
- Preserve tolerated legacy types, upstream field names, absent defaults, and unknown combo values. Loading and an
untouched editor/URI/mapping round trip are observational; explicit user edits may normalize only the represented
field.
- Preserve tolerated legacy types, upstream field names, absent defaults, and unknown combo values through mapping
and untouched-editor round trips. URI round trips cover supported share-link fields only. Explicit user edits may
normalize the represented field; runtime validation may reject values that observational loading must preserve.
- Subscription import is allowed only through supported Hysteria 1 protocol handlers. Subscription identity and test
metadata stay in `ServerProfile`, and validation diagnostics never disclose passwords or complete links.
- Runtime and download-test preparation use independent configuration copies. This backend uses application tun2socks
when global TUN requires it and owns the MMDB/ACL inputs used by its routing launch; it does not gain native TUN by
falling through another backend’s policy.
- 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.
+5 -5
View File
@@ -1,8 +1,7 @@
# Hysteria 2 guidance
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.
Hysteria 2's nested upstream document, native-TUN capability, statistics, and editor projection.
## Native document and editor projection
@@ -24,12 +23,13 @@ capability, statistics, and editor projection.
- 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.
from merely having a running Hysteria2 process. The configured server statistics target is separate from the
client's local readiness endpoint; capability availability does not imply a usable target was configured.
- 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
projection preservation, 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`.
+3 -4
View File
@@ -1,8 +1,7 @@
# Xray guidance
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 JSON preservation, routing/assets/statistics, and protocol/transport/TLS projections.
## Full-document preservation
@@ -23,8 +22,8 @@ and protocol/transport/TLS projections.
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.
Action providers retain reusable routing/asset windows through the created action owner and create transient
settings dialogs per request; the capability registry does not become a transient-window owner.
- 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.
+7 -6
View File
@@ -1,22 +1,23 @@
# Controller guidance
Inherit the root and package guides. This scope preserves controllers as process-lifetime authorities for shared
transitions, not owners of execution resources or presentation objects.
transitions. Services own execution resources; existing prompts are presentation compatibility paths.
## Shared state authorities
- Controllers own process-lifetime shared state and transition policy. They coordinate injected repositories/services
and publish structured Qt signals; they do not own transient widgets, network replies, core processes, or worker pools.
and publish structured Qt signals. New behavior delegates presentation and execution resources to their owners;
existing host-setting prompts do not justify moving network replies, core processes, or pools into controllers.
- `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
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.
- The active live profile is not the prepared document used by an already-started runtime. Resolve identity and
generation before changing state or host effects, and preserve typed runtime failures; cancellation and supersession
are not generic connection errors.
- `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
+3 -3
View File
@@ -1,8 +1,7 @@
# Embedded runtime guidance
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.
This scope owns reusable embedded execution machinery and application tun2socks; 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.
@@ -19,7 +18,8 @@ application tun2socks, while connection policy remains outside it.
- Child targets never touch Qt widgets. Output transport is non-blocking and bounded in message size, pending volume, and
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.
must not leave timers, callbacks, queues, or process handles alive. Stopping execution is not QObject destruction:
disposal must also release monitors and output infrastructure, including for a runtime that was never started.
- 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`;
+2 -1
View File
@@ -12,7 +12,8 @@ application-data or settings directory.
- Markdown files in this directory are repository metadata, not runtime data. Keep top-level and nested Markdown files
excluded consistently from setuptools package data and Nuitka inclusion while preserving them in the source tree.
- `Deploy.py --download` performs a networked refresh and may rewrite large, time-varying assets. Run it only when that
mutation is explicitly in scope; review source, checksums, exact changed files, and existing user modifications.
mutation is explicitly in scope; inspect its actual integrity checks, provenance, exact changed files, and existing
user modifications. A backend's digest-verified runtime updater does not establish this build downloader's guarantees.
## Local endpoint map
+4 -3
View File
@@ -1,8 +1,7 @@
# Bundled extension guidance
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.
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. New extension contracts must be usable without private
@@ -15,7 +14,9 @@ private authority merely because the code is bundled.
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.
all shared parser state and caches, not merely absence of widgets in the immediate method. Worker preparation also
requires the selected protocol handlers to opt in; a safe envelope decoder cannot authorize an unsafe downstream
parser. Preserve the GUI compatibility fallback for unclassified capabilities.
- 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.
+5 -4
View File
@@ -11,12 +11,13 @@ human-reviewed translations.
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.
- Preserve existing translation-key and language-field order. The generator retains dictionary order rather than
enforcing a universal sort; source traversal can affect newly discovered entries. Do not sort the catalog as cleanup.
`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.
meaning. Curated, verified translations need `isReviewed` set to the string `'True'`, as the generator compares that
literal; a Python Boolean is not equivalent. Review applies to the entry, so inspect its other language values too.
Do not clear approved review flags or hand-maintain the generated `source` module list.
## Extractable source text
+3 -2
View File
@@ -26,8 +26,9 @@ for unrelated application orchestration to accumulate in a broad helper namespac
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.
- `CleanupOnExit` and translation/theme/connection pools are weak registries, not owners. Cleanup normally
de-duplicates by type; repeated instances with separate resources require per-instance cleanup registration or an
explicit containing cleanup stage. Registry membership neither retains a wrapper nor proves every instance drained.
- `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
+2 -1
View File
@@ -24,7 +24,8 @@ satisfy without importing application composition or concrete backends.
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.
callbacks. A zero process exit can still be an unexpected connection failure; requested stop and raw exit success
are different facts. Keep semantic startup errors separate from 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
+2 -1
View File
@@ -22,7 +22,8 @@ Qt presentation, plugin discovery, or workflow execution.
- 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.
testing. Equal fingerprints do not imply equal profile IDs: independently stored profiles may describe identical
connections. Do not merge their metadata, ownership, or selection merely to deduplicate execution work.
- 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.
+5 -6
View File
@@ -1,8 +1,7 @@
# Plugin guidance
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.
capability definitions, atomic registration, dispatch, and plugin lifecycle; backend policy remains in each implementation.
## Contracts and registry
@@ -34,10 +33,10 @@ and plugin lifecycle; concrete backend policy remains in each implementation.
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. The registry's existing
synchronous `startCoreRuntime()` wrapper separately returns runtime/success for compatibility; preserve ownership
on start failure.
starts with zero arguments, raises typed startup failures, and exposes readiness separately. An alternate result
shape requires an explicit contract/version migration, not an implicit adapter inferred from built-in factories.
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
+8 -3
View File
@@ -9,7 +9,8 @@ primitives; pages and services consume them without creating parallel registries
## Canonical presentation
- Reuse `Furious.Qt` `AppQ*` controls, `AppStyleSheet`, translation/theme mixins, and shared dialog/window infrastructure.
Do not create parallel style, theme-transition, translation, or lifetime registries.
Do not create parallel style, theme-transition, translation, or lifetime registries. Shared control styling belongs
in the application stylesheets; component-specific overrides are valid parts of stylesheet composition.
- Controls that retranslate retain source text; semantic/user-defined values stay untranslated. Preserve keyboard focus,
shortcut scope, accessibility, translated-text growth, responsive layout, high-DPI behavior, and both themes.
- Application-owned theme transitions commit destination state immediately; snapshots are non-interactive presentation
@@ -55,9 +56,13 @@ primitives; pages and services consume them without creating parallel registries
- Top-level windows use canonical first-show preparation. Save geometry/state only after a native presentation; a
never-shown Qt fallback must not overwrite persisted user geometry. Do not call overridable geometry hooks from
constructors or manipulate private first-show state.
- A stylesheet border radius paints a rounded frame but does not clip child viewports or table headers. Padding
can protect the corners while introducing a visible inset; assess both effects before changing shared view styles.
Popup native-window transparency is a separate boundary from in-window child painting.
- When behavior depends on focus, selection, proxy mapping, modifiers, shortcuts, queued delivery, animation, geometry,
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.
or destruction, use real widgets, `QTest`, and the event loop. Prefer semantic assertions; for rendering defects,
test the affected border/background/alpha behavior under explicit themes and scale factors instead of relying on
selector counts or whole-window pixel equality.
- 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.
+2
View File
@@ -19,6 +19,8 @@ This scope owns restoration, migration, ordering, and persistence; workflows and
- 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.
Batched UI commands may commit several live mutations; cancellation prevents later batches without restoring
already committed ones. Do not impose whole-command atomicity without changing callers and failure semantics.
- 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
+8 -6
View File
@@ -10,12 +10,14 @@ for lifetime primitives. This scope owns multi-stage workflows and temporary res
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.
owner and explicit idempotent cleanup. Cancellation can suppress a result without stopping the underlying work;
distinguish deadline-bounded teardown from cooperative drains, and retain resources until their users finish.
Construct Qt services only after an application exists.
- Inject repositories/providers/clients/runtime factories where practical. Stage results, prove freshness, and commit
through the owning repository/controller rather than creating a parallel authoritative collection.
- Every async workflow defines supersession and one terminal path. Generation/version or exact target identity rejects
stale completion; terminal cleanup aborts/finishes once, deletes replies/Qt objects in their owning thread, and cannot
retain a shut-down manager.
stale completion. Terminal cleanup runs once and deletes replies/Qt objects in their owning thread. Release callback
contexts when execution no longer needs them; late delivery must not revive a shut-down manager or mutate live state.
## Connection and network workflows
@@ -39,9 +41,9 @@ for lifetime primitives. This scope owns multi-stage workflows and temporary res
unclassified plugin parsers stay on the GUI compatibility path. The manager's synchronous shutdown closes
admission, cancels work, and retains the pool/relay until workers finish. A slow-shutdown warning is diagnostic,
not a deadline that permits destroying running workers; a non-returning plugin can still block shutdown.
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
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
+3 -3
View File
@@ -17,9 +17,9 @@ general-purpose utility bucket.
- 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.
- Fallback presentation runs in the parent after a nonzero child result. It constructs a Qt application for the
report but does not call the ordinary application `run()` initialization. Keep that constructor dependency in
failure-path tests, and preserve the original result when evolving reporting failures rather than adding a 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.
+7 -2
View File
@@ -1,8 +1,8 @@
# Reusable widget guidance
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.
scope covers reusable controls and model/view adapters below page composition. Persistent widgets currently host
some service owners; that construction detail does not make every view an independent workflow authority.
## Presentation and identity
@@ -29,6 +29,11 @@ composition; it does not own application workflows.
- 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.
- Bulk profile mutations validate/prepare a batch before beginning structural notifications. Resolve captured IDs
again after confirmation and between deferred batches, report actual source ranges, and preserve activation before
observers see completed removal. Forward bulk insert/delete operations through the model instead of replaying a
single-item notification/reconciliation path for every profile. Small direct operations and deferred large ones
share these identity rules; batch yields and throttled progress updates serve different responsiveness purposes.
- 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.
+3 -3
View File
@@ -1,14 +1,14 @@
# Window and page guidance
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.
This scope owns persistent page composition and top-level presentation, not shared domain state.
## Composition and shared state
- `MainWindow` owns the persistent built-in page tree and navigation; plugin pages enter through the plugin navigation
service. Pages adapt shared controllers/services/repositories and must not become competing state authorities.
Preserve application-facing forwarding APIs until their consumers migrate deliberately.
Preserve application-facing forwarding APIs until their consumers migrate deliberately. Bulk profile forwarding
must retain the bulk mutation boundary through Home and its model, without expanding into per-profile refreshes.
- Home, Settings, tray actions, and reusable dialogs render the same connection, routing, and settings controllers.
Platform/capability availability affects presentation but does not authorize an unsupported persisted value or a
duplicate host side effect.
+3 -2
View File
@@ -5,8 +5,9 @@ resource-manifest contract; it does not govern general UI layout.
- Reuse an existing semantic icon before introducing a new asset. SVG sources stay compact vectors without scripts,
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.
- Use the shared icon helpers and the bundled monochrome/default and white variants as appropriate. An SVG's
`currentColor` alone does not establish Qt theme behavior; verify how `Furious/Qt/QtGui.py` resolves and masks the
chosen asset. Reuse that path instead of adding control-specific recoloring, 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 selected
environment's `pyside6-rcc Resources.qrc -o Furious/Frozenlib/AppResources.py`. Never hand-edit generated resource
+7 -2
View File
@@ -15,6 +15,8 @@ and test-tier selection; test convenience never weakens a production invariant.
hermetic child, temporary settings, disabled singleton/tray/restoration, and mocked host mutation.
- Import order is part of isolation: select the offscreen Qt platform and temporary settings identity before importing
modules that can create Qt/application globals. A late patch is not equivalent to preventing the side effect.
A temporary QSettings namespace does not reset already-cached `Storage` collections: explicitly isolate and restore
live repository fixtures as well as persisted settings, especially when exercising cleanup or partial startup.
## Test the contract
@@ -28,6 +30,8 @@ and test-tier selection; test convenience never weakens a production invariant.
duplicate endpoints, bounded scheduling, and unrelated-work preservation rather than relying on row positions.
- Qt behavior involving focus, selection, proxy mapping, shortcuts, queued delivery, geometry, animation, or destruction
uses real widgets and `QTest`. Localized-text tests choose an explicit language inside `isolatedSettings()`.
Rendering regressions may assert targeted pixel/alpha or geometry properties under explicit themes and scaling.
Stylesheet selector counts are not rendering invariants: shared rules and component overrides can both be valid.
- Prefer exact state, signal counts, destroyed signals, weak references, registry/child counts, thread/process/handle
ownership, and final exit status. RSS/handle trends and repeated lifecycle batches belong in stress tiers;
`gc.collect()` is diagnostic at batch boundaries, never a production fix or per-cycle requirement.
@@ -41,8 +45,9 @@ and test-tier selection; test convenience never weakens a production invariant.
- 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.
- 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.
- 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,