From 461bc3e9492dcab2fd9536f4601035c33488e3fe Mon Sep 17 00:00:00 2001 From: Loren Eteval Date: Wed, 7 Oct 2026 23:34:18 +0800 Subject: [PATCH] Refine repository guidance Signed-off-by: Loren Eteval --- .github/AGENTS.md | 3 +++ AGENTS.md | 4 ++++ Furious/AGENTS.md | 2 ++ Furious/Actions/AGENTS.md | 3 +++ Furious/Application/AGENTS.md | 2 ++ Furious/Backends/AGENTS.md | 2 ++ Furious/Backends/ExternalCore/AGENTS.md | 1 + Furious/Backends/Hysteria1/AGENTS.md | 2 ++ Furious/Backends/Hysteria2/AGENTS.md | 2 ++ Furious/Backends/Xray/AGENTS.md | 2 ++ Furious/Controllers/AGENTS.md | 3 +++ Furious/Core/AGENTS.md | 2 ++ Furious/Data/AGENTS.md | 2 ++ Furious/Extensions/AGENTS.md | 2 ++ Furious/Externals/AGENTS.md | 2 ++ Furious/Frozenlib/AGENTS.md | 3 +++ Furious/Interface/AGENTS.md | 2 ++ Furious/Models/AGENTS.md | 2 ++ Furious/Plugins/AGENTS.md | 2 ++ Furious/Qt/AGENTS.md | 2 ++ Furious/Repository/AGENTS.md | 2 ++ Furious/Service/AGENTS.md | 7 +++---- Furious/Utility/AGENTS.md | 3 +++ Furious/Widget/AGENTS.md | 6 +++--- Furious/Window/AGENTS.md | 2 ++ Icons/AGENTS.md | 2 ++ tests/AGENTS.md | 2 ++ 27 files changed, 62 insertions(+), 7 deletions(-) diff --git a/.github/AGENTS.md b/.github/AGENTS.md index 83baa02..939a965 100644 --- a/.github/AGENTS.md +++ b/.github/AGENTS.md @@ -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 diff --git a/AGENTS.md b/AGENTS.md index 2da8f85..9b2d82f 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -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 diff --git a/Furious/AGENTS.md b/Furious/AGENTS.md index 0dbee66..006a159 100644 --- a/Furious/AGENTS.md +++ b/Furious/AGENTS.md @@ -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 diff --git a/Furious/Actions/AGENTS.md b/Furious/Actions/AGENTS.md index fe090f4..4f38b94 100644 --- a/Furious/Actions/AGENTS.md +++ b/Furious/Actions/AGENTS.md @@ -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 diff --git a/Furious/Application/AGENTS.md b/Furious/Application/AGENTS.md index 3c992cb..a16263e 100644 --- a/Furious/Application/AGENTS.md +++ b/Furious/Application/AGENTS.md @@ -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. diff --git a/Furious/Backends/AGENTS.md b/Furious/Backends/AGENTS.md index 85232e7..488524e 100644 --- a/Furious/Backends/AGENTS.md +++ b/Furious/Backends/AGENTS.md @@ -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 diff --git a/Furious/Backends/ExternalCore/AGENTS.md b/Furious/Backends/ExternalCore/AGENTS.md index 00b676f..f14849e 100644 --- a/Furious/Backends/ExternalCore/AGENTS.md +++ b/Furious/Backends/ExternalCore/AGENTS.md @@ -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. diff --git a/Furious/Backends/Hysteria1/AGENTS.md b/Furious/Backends/Hysteria1/AGENTS.md index 7f42a7a..4de741c 100644 --- a/Furious/Backends/Hysteria1/AGENTS.md +++ b/Furious/Backends/Hysteria1/AGENTS.md @@ -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`, diff --git a/Furious/Backends/Hysteria2/AGENTS.md b/Furious/Backends/Hysteria2/AGENTS.md index e88d05b..ee77284 100644 --- a/Furious/Backends/Hysteria2/AGENTS.md +++ b/Furious/Backends/Hysteria2/AGENTS.md @@ -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. diff --git a/Furious/Backends/Xray/AGENTS.md b/Furious/Backends/Xray/AGENTS.md index 03e204e..a5b5c86 100644 --- a/Furious/Backends/Xray/AGENTS.md +++ b/Furious/Backends/Xray/AGENTS.md @@ -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. diff --git a/Furious/Controllers/AGENTS.md b/Furious/Controllers/AGENTS.md index 5c646c0..b6c672b 100644 --- a/Furious/Controllers/AGENTS.md +++ b/Furious/Controllers/AGENTS.md @@ -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 diff --git a/Furious/Core/AGENTS.md b/Furious/Core/AGENTS.md index 00304ee..03459d7 100644 --- a/Furious/Core/AGENTS.md +++ b/Furious/Core/AGENTS.md @@ -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. diff --git a/Furious/Data/AGENTS.md b/Furious/Data/AGENTS.md index d81ae6c..0c16f60 100644 --- a/Furious/Data/AGENTS.md +++ b/Furious/Data/AGENTS.md @@ -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 diff --git a/Furious/Extensions/AGENTS.md b/Furious/Extensions/AGENTS.md index 21c4f0a..15e3c04 100644 --- a/Furious/Extensions/AGENTS.md +++ b/Furious/Extensions/AGENTS.md @@ -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 diff --git a/Furious/Externals/AGENTS.md b/Furious/Externals/AGENTS.md index 8363e3c..81f3c60 100644 --- a/Furious/Externals/AGENTS.md +++ b/Furious/Externals/AGENTS.md @@ -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. diff --git a/Furious/Frozenlib/AGENTS.md b/Furious/Frozenlib/AGENTS.md index 919fc0b..1d9645b 100644 --- a/Furious/Frozenlib/AGENTS.md +++ b/Furious/Frozenlib/AGENTS.md @@ -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 diff --git a/Furious/Interface/AGENTS.md b/Furious/Interface/AGENTS.md index d229d4f..c9fdba7 100644 --- a/Furious/Interface/AGENTS.md +++ b/Furious/Interface/AGENTS.md @@ -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. diff --git a/Furious/Models/AGENTS.md b/Furious/Models/AGENTS.md index 3fe3c82..38c765d 100644 --- a/Furious/Models/AGENTS.md +++ b/Furious/Models/AGENTS.md @@ -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. diff --git a/Furious/Plugins/AGENTS.md b/Furious/Plugins/AGENTS.md index 72c9179..2e05826 100644 --- a/Furious/Plugins/AGENTS.md +++ b/Furious/Plugins/AGENTS.md @@ -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 diff --git a/Furious/Qt/AGENTS.md b/Furious/Qt/AGENTS.md index f9a2983..6177018 100644 --- a/Furious/Qt/AGENTS.md +++ b/Furious/Qt/AGENTS.md @@ -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 diff --git a/Furious/Repository/AGENTS.md b/Furious/Repository/AGENTS.md index 65e60f6..af26695 100644 --- a/Furious/Repository/AGENTS.md +++ b/Furious/Repository/AGENTS.md @@ -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 diff --git a/Furious/Service/AGENTS.md b/Furious/Service/AGENTS.md index 29e5d1c..409132a 100644 --- a/Furious/Service/AGENTS.md +++ b/Furious/Service/AGENTS.md @@ -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 diff --git a/Furious/Utility/AGENTS.md b/Furious/Utility/AGENTS.md index bb1e2d2..53f7585 100644 --- a/Furious/Utility/AGENTS.md +++ b/Furious/Utility/AGENTS.md @@ -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 diff --git a/Furious/Widget/AGENTS.md b/Furious/Widget/AGENTS.md index 40179d1..9ed036e 100644 --- a/Furious/Widget/AGENTS.md +++ b/Furious/Widget/AGENTS.md @@ -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. diff --git a/Furious/Window/AGENTS.md b/Furious/Window/AGENTS.md index d068708..481aa74 100644 --- a/Furious/Window/AGENTS.md +++ b/Furious/Window/AGENTS.md @@ -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 diff --git a/Icons/AGENTS.md b/Icons/AGENTS.md index 3272767..199d68e 100644 --- a/Icons/AGENTS.md +++ b/Icons/AGENTS.md @@ -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 diff --git a/tests/AGENTS.md b/tests/AGENTS.md index 32fffb1..5e47f74 100644 --- a/tests/AGENTS.md +++ b/tests/AGENTS.md @@ -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,