Refine repository guidance

Signed-off-by: Loren Eteval <loren.eteval@proton.me>
This commit is contained in:
Loren Eteval
2026-10-07 23:34:18 +08:00
parent f2f541d068
commit 461bc3e949
27 changed files with 62 additions and 7 deletions
+3
View File
@@ -37,6 +37,9 @@ 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.
- 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.
- Interpreter compatibility jobs install dependency versions that actually support each interpreter, then exercise
cold imports and real behavior. Grammar checks or newer-interpreter simulations do not substitute for those jobs.
Keep the full cross-platform regression suite distinct from focused version checks, and make required version
+4
View File
@@ -7,6 +7,8 @@
- 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.
- When guidance says A and code appears to do B, inspect the call path and tests. Decide whether B is intentional
@@ -107,6 +109,8 @@
`setup.py`, `requirements.txt`, `Deploy.py`, and the release workflow. Review every applicable surface rather than
assuming one declaration is canonical. Networked `Deploy.py --download` and destructive build cleanup run only when
explicitly in scope.
For native dependency updates, distinguish distribution metadata, loaded native revision, supported API, and
privileged host behavior. Each claim needs evidence from its own boundary and the selected artifact.
## Verification
+2
View File
@@ -20,6 +20,8 @@ Read `Furious/__init__.py` with `tests/test_public_api.py`; paths are relative t
when changing exports; trace transitive imports and public-import/packaging tests, not just the edited module.
Wildcard exports can force lazy attributes to load, so check ordinary, wildcard, and cold-process imports
separately. Importability means preserving the actual side-effect boundary, not merely avoiding a syntax error.
Python export aliases, distribution names, native-module names, and persisted identifiers serve different consumers;
inspect each affected surface before renaming one. An import alias does not migrate stored data or transfer ownership.
## State, data, and ownership
+3
View File
@@ -21,6 +21,9 @@ Read `Furious/Actions/Import.py` with `tests/test_qt_interactions.py`; paths are
- 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.
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.
## Lifetime, input, and verification
+2
View File
@@ -33,6 +33,8 @@ relative to this source tree's root.
endpoint, and fails closed when ownership is uncertain, including privilege handoff. A successful Windows
local-server listen alone does not establish exclusivity; command delivery and endpoint ownership are separate
observations.
A forwarded or unresolved launch must unwind its initial owners without restoring a connection or bootstrapping
ordinary UI. Constructing a Qt application for election or fallback reporting does not grant primary ownership.
- Each singleton IPC connection creates a short-lived socket sender. Use weak named dispatch with sender forwarding
to the application; repeatedly connecting a compiled application bound method can grow Nuitka's protection list
even after the native sockets die. The server owns sockets through their one-command completion/disconnection.
+2
View File
@@ -31,6 +31,8 @@ tree's root.
- `Furious/Plugins/Runtime.py` checks that serialization yields nonempty text and carries structured diagnostics on failure;
it does not parse pre-serialized strings or validate a backend's complete schema. Keep serialization success,
backend configuration acceptance, execution start, and readiness as separate evidence.
A serializer or editor accepting a document cannot establish that the native core accepts its unknown fields.
Preserve the document while reporting rejection at the actual backend boundary.
## TUN and runtime policy
+1
View File
@@ -34,6 +34,7 @@ source tree's root.
native core TUN support. Subscription decoding must continue to reject executable profiles.
The stored/API opt-in retains its tun2socks name for compatibility, but the application preference chooses the
engine. Validate its SOCKS transit specification for either engine without importing the executable's private schema.
Changing its presentation label must not rename the stored opt-in, infer native TUN, or select an application engine.
- The embedded backends' JSON serialization helper is not this launch boundary: External Core passes a structured
executable/argument/environment specification to `Popen`. Validate through `validateProcess()` and the launch path,
including non-finite timeout rejection, rather than assuming a serializable mapping is safe or executable.
+2
View File
@@ -28,6 +28,8 @@ 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.
- 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`,
+2
View File
@@ -13,6 +13,8 @@ this source tree's root.
- Preserve upstream names, optional-group absence, unknown siblings, and future string values. Effective defaults such
as `realm.ipMode` are presented without materializing them during an untouched save; editing one leaf changes only
that leaf.
A share URI is a projection of this document. Features omitted by its codec must survive JSON/editor round trips;
URI equality alone cannot prove that a nested client configuration was preserved.
- `obfs.type` selects tagged subtype data. Unknown types remain visible and survive untouched. An explicit switch to a
known type may remove incompatible subtype branches, but never unrelated document branches.
+2
View File
@@ -27,6 +27,8 @@ source tree's root.
- Xray owns routing profiles/options, geo assets, API statistics, and the `XRAY_LOCATION_ASSET` environment contract.
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.
A file chooser result is not an asset commit. Asset-window import follows the shared Qt modal-continuation rule;
`ModalPickerLifetimeTest` checks that a dead asset view receives no selected filename.
- Runtime asset updates stage bytes and digest verification before atomic replacement. Failure preserves the prior
usable file. Network reply and checksum worker have separate lifetimes: cancellation/shutdown must suppress late
hash publication as well as abort requests. The plugin capability owns its lazy updater through shutdown.
+3
View File
@@ -51,6 +51,9 @@ source tree's root.
Application-engine reconnect notices consult committed application-TUN ownership. Native-TUN and proxy-only
connections still save and publish the engine preference without requesting reconnection; see the preference-notice
cases in `tests/test_sing_tun.py`.
Persist stable choice identifiers, not translated labels or combo positions. Relabeling/reordering controls must
preserve an existing preference and the running connection's ownership. Selector retranslation and committed-TUN
ownership tests challenge those separate claims; a translated label alone proves neither.
- A completed disconnect restores usable UI state even if runtime cleanup failed. `Disconnected` and an empty
active-runtime snapshot therefore do not prove physical release: the service retains failed leases and blocks
new acquisition while they remain. Final controller shutdown surfaces unresolved cleanup and preserves the
+2
View File
@@ -58,3 +58,5 @@ relative to this source tree's root.
Binding-provided failure text is diagnostic input, not a stable enumerated protocol: preserve useful reasons rather
than accepting only exact known strings. Changing binding versions requires coordinated model validation,
distribution metadata/native-library inclusion, and workflow API checks; a successful import does not exercise TUN.
Where the binding exposes native provenance, verify it alongside the distribution version. Metadata from an
updated installation alone cannot prove that a spawned or compiled runtime loaded the intended native revision.
+2
View File
@@ -15,6 +15,8 @@ tree's root.
tests, setuptools package data, and Nuitka. Do not incidentally reformat generated ACLs or replace binary assets.
- 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.
Native binding resources, including an engine's embedded driver, have their own package/native owner. Their inclusion
is checked through that dependency and the release artifact, not by copying them into this data directory.
- `Deploy.py --download` performs a networked refresh and may rewrite large, time-varying assets. Run it only when that
mutation is explicitly in scope; inspect integrity checks, provenance, exact changed files, and user modifications.
Validate each downloaded file and the consumer's expected format. Build downloads currently write destination
+2
View File
@@ -23,6 +23,8 @@ 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
+2
View File
@@ -20,6 +20,8 @@ tree's root.
new unreviewed one. Review wording changes as translation migrations, including reused keys in other modules.
For newly added or intentionally edited entries, keep fields in the preferred `source`, `RU`, `ZH`, `isReviewed`
order. This is a local editing convention, not permission to reorder untouched catalog entries or sort source keys.
A deliberate source-key rename migrates the reviewed language values as well as the English key. Preserve their
order and verify both languages before retaining review status; extraction still owns the rebuilt source list.
- Inspect the full diff. Preserve deliberate translations/review flags, HTML/newline semantics, and natural RU/ZH
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.
+3
View File
@@ -18,6 +18,9 @@ Read `Furious/Frozenlib/AppSettings.py` with `tests/test_frozenlib.py`; paths ar
strict legacy API shapes and real blocked/queued workers.
- `Globals` exposes only deliberate application-lifetime owners. Accessors may be absent during partial startup,
isolated tests, or teardown; do not add fallback global owners that create competing lifecycles.
- `Mixins.qObjectIsValid` checks native QObject validity and deliberately accepts non-QObjects, including `None`.
Check required presence and plain resource state separately; a Python editor binding needs checks of its Qt fields.
Neither one-object nor grouped validity checks provide ownership, thread affinity, or generation freshness.
- `AppSettings` keys include preferences and encoded repository blobs. Preserve names, defaults, string/binary
encodings, migrations, and import-time registration. `AppSettings.get()` can persist a default or repair an
invalid preference; it is not an observational reader like a copied customization projection. Distinguish
+2
View File
@@ -25,6 +25,8 @@ Read `Furious/Interface/Runtime.py` with `tests/test_interface.py`; paths are re
- `StorageBackend.data()` deliberately exposes a live mutable collection for compatibility. Do not reinterpret it as a
snapshot or introduce a second authoritative cache. Editor bindings map input to configuration and back; they do not
decide runtime, persistence, or host policy.
The interface supplies no atomic disk-flush or malformed-input recovery guarantee. Those belong to the concrete
repository and must be established through its restore/commit failure paths.
- `ApplicationRunner.ExitCode` is the outer application process protocol; it is not interchangeable with a core's
raw exit code or `RuntimeExitReason`. Preserve the meaning at each boundary instead of translating every nonzero
value into one generic failure.
+2
View File
@@ -27,6 +27,8 @@ root.
Replacing a connection preserves the logical profile's metadata/ID but may create a new wrapper. Consumers must
choose explicitly between logical identity and exact-object ownership; neither copying nor equal IDs transfers
a live repository or runtime reference automatically.
Independent copies retain local metadata such as favorites and annotations while resetting remote ownership.
Keep that policy in the domain copy operation; reconstructing only connection JSON loses the metadata contract.
- 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.
+2
View File
@@ -23,6 +23,8 @@ tree's root.
- Failure policy belongs to the dispatch operation. Automatic subscription detection tries decoders by priority; an
explicitly selected decoder restricts candidates. URI dispatch selects the registered scheme owner rather than
probing unrelated handlers after failure. Keep required-operation failures observable without secret payloads.
Plugin/capability IDs and type ownership define dispatch; display names and translated labels do not. A presentation
rename must not change registration identity or silently migrate a saved provider choice.
## Ownership and compatibility
+2
View File
@@ -104,6 +104,8 @@ Use the `manage-qt-pyside6-lifetimes` skill for source lifetime work when availa
follow-up UI. A pure Python editor binding can survive its destroyed Qt field tree. Publication after a data
commit may also destroy the presenter: retain the committed outcome while stopping stale UI work, including
the close-confirmation caller. `ModalPickerLifetimeTest` in `tests/test_qt_lifetime.py` challenges these boundaries.
Capture required editor data before opening an existing file for writing. Opening it can truncate it immediately;
accessing a stale widget afterward cannot be repaired by catching the resulting exception.
- Queued delivery never transfers ownership implicitly. The sender may finish before delivery, so callbacks resolve a
still-valid receiver and current generation in the receiver's Qt thread before touching widgets, models, or wrappers.
A zero-delay timer yields work but does not establish ordering against an unrelated Qt event. Express required
+2
View File
@@ -18,6 +18,8 @@ to this source tree's root.
metadata precedence are migration behavior: legacy `UserServer` aliases override nested metadata, and explicit
top-level current fields then override those aliases. Preserve this order and unknown extras unless a tested
migration deliberately changes it; do not treat every duplicate key as interchangeable.
Connection JSON export is not a profile-store backup. Verify durable metadata through storage-record/backend
round trips, including identity, favorites and remote ownership, rather than connection serialization alone.
- A restore failure remains observable. Automatic cleanup must not replace unreadable persisted bytes with an
empty fallback; only an explicit successful replacement may do so. Root decoding, complete-collection
hydration, live replacement, and later serialization are separate failure boundaries. Byte preservation does
+3 -4
View File
@@ -11,10 +11,9 @@ source tree's root.
collections, and UI owns presentation. Prefer outcome signals/callbacks for new service APIs. `UpdateManager`
still creates update dialogs as a compatibility path; preserve its public behavior until presentation is
deliberately moved to a UI owner.
- Give each QObject service, worker, reply, timer, pool, thread, runtime, process, cache, and callback context one durable
owner and 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.
- A workflow keeps its execution resources and callback context owned until their users finish. Cancellation may
suppress publication while execution continues; distinguish bounded teardown from cooperative drains and keep
cancelled work inside admission/resource limits. Construct Qt services only after an application exists.
- Native owner destruction requires a final cleanup attempt for Python-owned resources; it does not terminate
running Python work. At `destroyed`, the owner's wrapper is invalid
but its QObject children have not yet been deleted; a plain weak-reference callback may release Python state
+3
View File
@@ -14,6 +14,9 @@ source tree's root.
factory; the parent must not construct a Qt application to pass across the process boundary. Signal handlers are
installed only after the factory returns, so pre-construction signals are outside this wrapper's handler coverage.
Preserve semantic exit codes and original exception/traceback context; crash-log failure is secondary.
Verify this through a real spawned child: multiprocessing bootstrap can intercept an uncaught factory/run failure
before `sys.excepthook`. Direct hook tests prove its mapping only, not dispatch from every child failure path;
compare the actual exit and crash flag before claiming supervision coverage.
- The parent entry point joins only the child it created and shows the fallback Qt report only for a nonzero result.
That join follows the GUI session lifetime; it is not a short startup-readiness deadline. Tests must bound their
own waits and reap their exact child if the fixture fails. A child stuck in cooperative worker cleanup can
+3 -3
View File
@@ -32,9 +32,9 @@ source tree's root.
- `ServerTableView` owns selection and cell repaint for profile tests, while `ProfileTestManager` owns scheduling,
concurrency, temporary runtimes, cancellation, stable-target validation, and latency/speed mutation. Repository or
subscription changes are forwarded as invalidation boundaries; stale results never write by row.
- Models, delegates, headers, menus, actions, animations, spinners, WebEngine/map objects, timers, workers, and replies
each need one owner. Persistent widgets connect once and refresh state; visibility may pause rendering/animation, not
application-level log draining, traffic collection, or other service ownership.
- Persistent widgets reuse their model, delegates and signal paths during refresh; replacement needs explicit
retirement of the former owned tree. Visibility may pause rendering/animation, not application-level log draining,
traffic collection, or other service ownership.
A view may borrow a model, delegate, or controller; installing one is not a transfer of QObject ownership.
Parent newly created presentation objects to their intended owner and retire replacements at the creating
boundary, while preserving explicitly shared owners. Test native owner-first teardown with wrappers retained.
+2
View File
@@ -47,6 +47,8 @@ Read `Furious/Window/MainWindow.py` with `tests/test_ui_behavior.py`; paths are
windows and retained settings dialogs need an explicit owner and reopen policy. Classify a plugin-created page or
dialog by the lifetime transferred to its caller, not by the registry's process lifetime. A settings label or Qt
parent does not determine lifetime: inspect the base class and close/accept/reject path before changing deletion policy.
A successful save is a data outcome, not proof that its window or confirmation prompt remains valid. Apply the Qt
continuation rule in both the saving method and its close caller; window destruction does not roll back a committed save.
- Empty-state presentation distinguishes an empty repository from a filtered view with no matches. Recovery changes
view filters only; reuse existing import/edit/test actions instead of creating page-specific workflow owners.
- Use normal layouts and `AppQ*` controls. Restore top-level geometry only after persistent composition and through the
+2
View File
@@ -26,6 +26,8 @@ Read `Resources.qrc` with `tests/test_public_api.py`; paths are relative to this
- Resource identity is prefix plus alias: default and white collections intentionally repeat aliases under
different prefixes. Check duplicate full paths and missing inputs, then exercise a compiled-resource consumer;
a source file on disk and successful `pyside6-rcc` execution do not prove the expected alias resolves.
Preserve the prefix at consumers when changing a glyph; equal filenames in different collections are not the same
themed resource. Test the helper-selected variant rather than loading an arbitrary SVG path for comparison.
- 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
+2
View File
@@ -30,6 +30,8 @@ Read `tests/support.py` with `tests/README.md`; paths are relative to this sourc
- Small workflow tests compose real shared controllers, models, and signals across the relevant UI surfaces;
mock the external effect instead of replacing the authority whose consistency is under test. A mocked reconnect
proves a request was issued, not which document a real runtime launched.
A directly invoked exception hook does not prove that a spawned process routes factory/run exceptions through it.
For supervision claims, retain the real child exit/crash-result boundary and bound/reap that exact test process.
- For staged changes, fail immediately before commit and prove live plus persisted state is unchanged. Test a
post-commit side-effect failure separately. Keep persisted-profile assertions distinct from runtime-copy output.
- Use stable profile/subscription identities in reconciliation and async tests. Exercise supersession, removal/reorder,