From 8fb02d3b59a95b416bb2e3f5d9b893cf12f159ca Mon Sep 17 00:00:00 2001 From: Loren Eteval Date: Sat, 19 Sep 2026 12:52:51 +0800 Subject: [PATCH] Refine repository guidance Signed-off-by: Loren Eteval --- .github/AGENTS.md | 6 ++++-- AGENTS.md | 4 +++- Furious/AGENTS.md | 5 +++-- Furious/Actions/AGENTS.md | 7 ++++--- Furious/Application/AGENTS.md | 9 +++++---- Furious/Backends/AGENTS.md | 5 +++-- Furious/Backends/ExternalCore/AGENTS.md | 7 +++++-- Furious/Backends/Hysteria1/AGENTS.md | 6 +++--- Furious/Backends/Hysteria2/AGENTS.md | 3 ++- Furious/Backends/Xray/AGENTS.md | 9 +++++---- Furious/Controllers/AGENTS.md | 5 ++++- Furious/Core/AGENTS.md | 6 ++++-- Furious/Data/AGENTS.md | 5 +++-- Furious/Extensions/AGENTS.md | 6 +++--- Furious/Externals/AGENTS.md | 4 +++- Furious/Frozenlib/AGENTS.md | 5 +++-- Furious/Interface/AGENTS.md | 5 +++-- Furious/Models/AGENTS.md | 6 ++++-- Furious/Plugins/AGENTS.md | 2 ++ Furious/Qt/AGENTS.md | 4 +++- Furious/Repository/AGENTS.md | 4 +++- Furious/Service/AGENTS.md | 8 +++++--- Furious/Utility/AGENTS.md | 5 +++-- Furious/Widget/AGENTS.md | 5 +++-- Furious/Window/AGENTS.md | 5 +++-- Icons/AGENTS.md | 2 ++ tests/AGENTS.md | 4 +++- 27 files changed, 91 insertions(+), 51 deletions(-) diff --git a/.github/AGENTS.md b/.github/AGENTS.md index 6e7621c..20c20f9 100644 --- a/.github/AGENTS.md +++ b/.github/AGENTS.md @@ -49,5 +49,7 @@ exceptions; it does not define the source test suite or imply that every package source verification. Follow actual `needs` and tag gates back to required checks; upload success alone does not establish release eligibility. A diagnostic Nuitka build that changes compiler/runtime flags is separate evidence from the ordinary release configuration; record and exercise the latter before claiming a packaged defect resolved. -- 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. +- Revalidate version/architecture claims against the current matrix instead of duplicating all pins here. Record + which workflow invocation and effective dependency set produced an artifact; a passing standalone binary job + does not inherit source-test evidence from a different invocation. When topology changes, follow every consumer + through upload and publication and update this scope. diff --git a/AGENTS.md b/AGENTS.md index fc61559..df8c4e9 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -105,7 +105,9 @@ elapsed timeout is not evidence of native resource release; distinguish that observation from the intended guarantee. - Report source inspection, executed tests, mocked platform evidence, and packaged validation separately. A passing source suite does not prove native distributions or every declared Python/Qt floor. Release import checks do not - replace behavioral tests; record untested targets and compatibility gaps explicitly. + replace behavioral tests; record untested targets and compatibility gaps explicitly. Match verification to the + changed contract: guidance-only work checks claims, references, scope, and path preservation; formatting-only work + checks the promised structural equivalence. Neither warrants unrelated code changes or generated-file refreshes. - 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; use targeted rendering assertions when pixels are the defect, without relying on whole-window snapshots or arbitrary sleeps. diff --git a/Furious/AGENTS.md b/Furious/AGENTS.md index 6635fe8..9964e4e 100644 --- a/Furious/AGENTS.md +++ b/Furious/AGENTS.md @@ -14,8 +14,9 @@ place. presentation in `Qt`, `Widget`, `Window`, or `Actions`. - `Interface` and `Models` stay dependency-light and must not import UI, controllers, services, repositories, or concrete backends. Backend/runtime modules remain importable without constructing editors or the application. -- Package `__init__.py` files are curated compatibility surfaces, not mirrors. Import order can register settings or - affect lazy plugin/Nuitka discovery; search public-import and packaging tests before changing exports. +- Package `__init__.py` files are curated compatibility surfaces, not mirrors. Import-time settings registration and + lazy capability imports are distinct from application construction or plugin discovery. Preserve that distinction + when changing exports; trace transitive imports and public-import/packaging tests, not just the edited module. ## State, data, and ownership diff --git a/Furious/Actions/AGENTS.md b/Furious/Actions/AGENTS.md index 2900bf2..430bd38 100644 --- a/Furious/Actions/AGENTS.md +++ b/Furious/Actions/AGENTS.md @@ -36,9 +36,10 @@ owned commands and presentation without becoming a workflow authority. - 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. -- Resolve the live target when a command is triggered, then capture intended identities/input before yielding. On - confirmation, resolve those captured targets again rather than adopting a later selection. Progress reports actual - completed work; rejecting a progress dialog stops later batches and does not undo already inserted profiles. +- Capture intended identities/input before yielding. On confirmation, resolve those identities against current + repository/controller state; keep the captured target set even if selection changes, and skip targets that no + longer exist. Progress reports actual completed work; rejecting a progress dialog stops later batches and does + not undo already inserted profiles. - Verify command state and delegation, cancellation/error presentation, shortcut scope in the real focused widget, menu rebuild cleanup, and repeated dialog/capture/action lifetimes. Use `tests/test_qt_interactions.py`, `tests/test_ui_behavior.py`, and `tests/test_qt_lifetime.py` for focused diff --git a/Furious/Application/AGENTS.md b/Furious/Application/AGENTS.md index 117e305..748248e 100644 --- a/Furious/Application/AGENTS.md +++ b/Furious/Application/AGENTS.md @@ -9,10 +9,11 @@ boundary between the outer child-process supervisor and the inner application ev owners already exist during election. Plugins are available before repository restoration interprets persisted profiles. Register cleanup as each acquisition succeeds, including election-failure paths, and preserve these dependencies when changing stage order. -- Partial startup, normal exit, signals, and event-loop failure converge on one reverse-order cleanup path. Each - registered stage is attempted once and one failure does not skip later stages. This stack does not retry a failed - callback: service-level retry/retention obligations must be satisfied before its owner disappears. `exit()` requests - Qt termination; action/window/session handlers do not run cleanup directly. +- Partial startup, normal exit, signals, and event-loop failure converge on one reverse-order cleanup path. + `aboutToQuit` and the event-loop `finally` may both reach it; repeated entry must not repeat registered stages. + One callback failure does not skip later stages, but the stack does not retry it. Service-level retry/retention + obligations must be satisfied before the owner disappears. `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. Run service shutdown while its diff --git a/Furious/Backends/AGENTS.md b/Furious/Backends/AGENTS.md index a969d20..f0c2637 100644 --- a/Furious/Backends/AGENTS.md +++ b/Furious/Backends/AGENTS.md @@ -45,8 +45,9 @@ generic default. - Read the selected backend's nested guide before changing its configuration, editor, protocol codec, runtime, TUN, routing, asset, statistics, or process behavior. Those child guides own backend-specific compatibility details; keep this parent focused on rules that every backend must satisfy. -- A shared backend-contract change must be checked against Xray, Hysteria 1, Hysteria 2, and External Core rather than - making the most feature-rich backend the implicit default for the others. +- Check a shared backend-contract change against Xray, Hysteria 1, Hysteria 2, and External Core, including an absent + optional capability and a present capability that cannot perform the requested operation. Those are different + outcomes; neither permits shared code to substitute another backend's policy. ## Verification diff --git a/Furious/Backends/ExternalCore/AGENTS.md b/Furious/Backends/ExternalCore/AGENTS.md index 5ae5d68..b90883c 100644 --- a/Furious/Backends/ExternalCore/AGENTS.md +++ b/Furious/Backends/ExternalCore/AGENTS.md @@ -10,8 +10,11 @@ preserves the intentionally different direct-subprocess scope for user-selected TUN address, and application-tun2socks opt-in distinct while preserving unknown top-level fields. - Loading is observational: do not silently absolutize or rewrite relative paths. Validation before spawn owns path existence/type, argument and environment types/NULs, endpoint requirements, and a finite bounded shutdown timeout. -- Execute an argument vector with `shell=False`. Never concatenate a shell command, search or kill by process name, or - log arguments/environment values that may contain credentials. + Finite validation must reject non-finite numbers explicitly; range comparisons alone do not reject NaN. + `shutdownTimeout()` currently accepts NaN: this is a validation gap, not a supported timeout. +- Execute an argument vector with `shell=False`. Environment overrides apply to a copy of the inherited process + environment; preparation must not mutate the host's `os.environ`. Never concatenate a shell command, search or + kill by process name, or log arguments/environment values that may contain credentials. ## Runtime and TUN ownership diff --git a/Furious/Backends/Hysteria1/AGENTS.md b/Furious/Backends/Hysteria1/AGENTS.md index 0cbc4c9..f585520 100644 --- a/Furious/Backends/Hysteria1/AGENTS.md +++ b/Furious/Backends/Hysteria1/AGENTS.md @@ -10,9 +10,9 @@ exists to preserve Hysteria 1's legacy flat schema and lifecycle without importi 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. +- This backend participates in application tun2socks through the shared startup workflow; its factory does not own + host routing or connection commit. Keep MMDB/ACL launch preparation here and application-TUN acquisition/rollback + with that workflow. Hysteria 2 native-TUN policy does not apply to this legacy backend. - Routing ACL/MMDB launch inputs remain distinct from the stored connection JSON. Optional files are read into launch data before the child starts; a missing/unreadable file is logged and falls back to empty input. Preserve that observable fallback unless deliberately changing the contract, and include this synchronous file work in diff --git a/Furious/Backends/Hysteria2/AGENTS.md b/Furious/Backends/Hysteria2/AGENTS.md index 116cab2..cbc1e78 100644 --- a/Furious/Backends/Hysteria2/AGENTS.md +++ b/Furious/Backends/Hysteria2/AGENTS.md @@ -22,7 +22,8 @@ owns Hysteria 2's nested upstream document, native-TUN capability, statistics, a Failure to establish required managed server-route exclusions is terminal: use `TUNPreparationError` so registry dispatch cannot interpret it as permission to fall back to another TUN path. Probe/download copies always remove native TUN. Managed preparation currently resolves server addresses synchronously; asynchronous readiness does not - make that preparation interruptible. + make that preparation interruptible. Test resolved addresses and explicit route exclusions as separate inputs to + the exclusion guarantee; a resolution failure alone does not prove that valid manual exclusions are absent. - 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 diff --git a/Furious/Backends/Xray/AGENTS.md b/Furious/Backends/Xray/AGENTS.md index 1dd4111..925e6e5 100644 --- a/Furious/Backends/Xray/AGENTS.md +++ b/Furious/Backends/Xray/AGENTS.md @@ -34,10 +34,11 @@ owns Xray's full JSON preservation, routing/assets/statistics, and protocol/tran as a side effect of preparing a launch. - Routing-rule row moves mutate the live profile's rule list in matching order, with Qt move notifications preserving selection. Internal drag-and-drop, the Move menu, and list-scoped Ctrl+Up/Ctrl+Down shortcuts use this same model - mutation and preserve selected-row order. Pending rule editors/confirmations use persistent model indexes so moving or deleting - a rule cannot retarget their completion. Verify this through `tests/test_ui_behavior.py` and repository/runtime order - round trips. Rule-editing confirmations share the transient rules dialog as their Qt owner on every platform, - so owner destruction also ends pending confirmation callbacks. + mutation and preserve selected-row order. Pending rule editors/confirmations use persistent indexes in that exact + model: moves preserve their targets, while removal/reset can invalidate them and must suppress write-back. + Persistent indexes are not identities across model replacement. Verify this through `tests/test_ui_behavior.py` + and repository/runtime order round trips. Rule-editing confirmations share the transient rules dialog as their Qt + owner on every platform, so owner destruction also ends pending confirmation callbacks. - Statistics preparation is optional and may leave a valid runtime without a statistics target. Preserve that distinction from connection failure; later sampling uses the target captured for this runtime, not newly edited settings or an assumption based solely on the backend name. `configureXrayStats()` merges the required API service diff --git a/Furious/Controllers/AGENTS.md b/Furious/Controllers/AGENTS.md index ac94a58..444162c 100644 --- a/Furious/Controllers/AGENTS.md +++ b/Furious/Controllers/AGENTS.md @@ -15,7 +15,10 @@ compatibility paths. 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 exceptions, cancellation, or unexpected-exit - failure. Worker/native callbacks cross to the controller’s Qt thread before transition. + failure. Worker/native callbacks cross to the controller’s Qt thread before transition. Signal listeners and queued + actions can synchronously disconnect or replace a start. Required invariant: revalidate current state/operation + after invoking them before completing the connection or applying further host effects; a check before signal + emission alone cannot establish freshness afterward. - 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. Runtime commit, host-effect success, and visible connection state are distinct diff --git a/Furious/Core/AGENTS.md b/Furious/Core/AGENTS.md index 7ed7388..0684371 100644 --- a/Furious/Core/AGENTS.md +++ b/Furious/Core/AGENTS.md @@ -16,8 +16,10 @@ connection policy remains outside it. exit. - Required cleanup covers the exact child, process handle, monitor/drain timers, queues, callbacks, and feeder resources. Stop must bound waits, escalate only the owned child, and remain safe after partial start or repetition. - A join timeout or failed handle close is not a successful reap. Verify actual child liveness before describing a - terminal execution state as complete resource release; include failed escalation in ownership tests. + Execution exit, terminal-event delivery, and monitor/transport disposal need separate assertions; success at one + boundary must not hide a leak at another. A join timeout or failed handle close is not a successful reap. Verify + actual child liveness before describing a terminal execution state as complete resource release; include failed + escalation in ownership tests. `MultiprocessingRuntime._closeProcess()` currently discards its process reference even when handle close fails. This is a cleanup-contract gap, not a permissible ownership transfer: a fix must preserve observability of the outstanding child/handle and agree with the service lease's cleanup-failure semantics. diff --git a/Furious/Data/AGENTS.md b/Furious/Data/AGENTS.md index 57c8644..12201c6 100644 --- a/Furious/Data/AGENTS.md +++ b/Furious/Data/AGENTS.md @@ -26,8 +26,9 @@ provenance; it is not an application-data or settings directory. - Linux Essentials-only builds deliberately operate without WebEngine; map consumers must retain their non-WebEngine fallback. macOS/Windows packaged paths may include WebEngine and must resolve all local resources from the bundle. Audit map assets together with `Furious/Widget/EndpointInfoWidget.py`: local loading, the WebChannel bridge, remote - tile permissions, and external attribution navigation form one boundary. A CSP change alone does not establish - that arbitrary navigation or remote executable code is allowed by the host. + tile permissions, and external attribution navigation form one boundary. Validate both the renderer payload and + host-side acceptance when that bridge changes; editing bundled JavaScript alone cannot establish host behavior. + A CSP change alone does not establish that arbitrary navigation or remote executable code is allowed by the host. ## Verification diff --git a/Furious/Extensions/AGENTS.md b/Furious/Extensions/AGENTS.md index 5ecf886..02273ac 100644 --- a/Furious/Extensions/AGENTS.md +++ b/Furious/Extensions/AGENTS.md @@ -11,9 +11,9 @@ is bundled. `SubscriptionResult` envelope; nested mappings are not necessarily deeply immutable. Profile construction/metadata belongs to `SubscriptionImportService`, and group reconciliation, request generations, timers, persistence, and post-commit effects belong to the subscription service/repository path. -- Automatic detection probes decoders by priority; explicit selection does not authorize format substitution. Return - `None` for a mismatch. Recognizing a share-link envelope does not validate its URI schemes or protocols; the importer - owns that decision. Preserve useful names/upstream IDs and never log a complete payload or link. Current +- Automatic detection probes decoders by priority. An explicit decoder ID restricts dispatch to that decoder; + an unknown ID or a mismatch must not silently resume automatic detection. Return `None` for a mismatch. Recognizing + a share-link envelope does not validate its URI schemes or protocols; the importer owns that decision. Preserve useful names/upstream IDs and never log a complete payload or link. Current standard formats are plain/Base64 share-link envelopes; linear parsing is not an input-size bound. Introduce explicit size/depth/work limits before adding richer recursive or nested formats. - Worker safety is a property of the whole preparation path. Standard decoders opt in, but the selected protocol diff --git a/Furious/Externals/AGENTS.md b/Furious/Externals/AGENTS.md index 12bdc2b..453fb2f 100644 --- a/Furious/Externals/AGENTS.md +++ b/Furious/Externals/AGENTS.md @@ -22,7 +22,9 @@ structure and human-reviewed translations. Do not clear approved review flags or hand-maintain the generated `source` module list. Runtime lookup reverse-maps translated text to a source key through a shared reverse index across languages. Equal translations for different source keys can therefore affect later retranslation, including after a language switch. Exercise lookup and - retranslation under explicit locales rather than treating collision diagnostics as cosmetic. + retranslation under explicit locales rather than treating collision diagnostics as cosmetic. A collision-free + extraction report does not prove reverse lookup is unambiguous across every language; inspect the runtime index + and language-switch behavior when two source keys share translated text. ## Extractable source text diff --git a/Furious/Frozenlib/AGENTS.md b/Furious/Frozenlib/AGENTS.md index a5effa6..f5882de 100644 --- a/Furious/Frozenlib/AGENTS.md +++ b/Furious/Frozenlib/AGENTS.md @@ -9,8 +9,9 @@ boundaries, not a license for unrelated application orchestration to accumulate - `Globals` exposes only deliberate application-lifetime owners. Accessors may be absent during partial startup, isolated tests, or teardown; do not add fallback global owners that create competing lifecycles. - `AppSettings` keys include preferences and encoded repository blobs. Preserve names, defaults, string/binary - encodings, migrations, and import-time registration. Distinguish desired preferences from confirmed host effects; - startup-registration success is persisted only after its helper reports success. Settings storage and cached + encodings, migrations, and import-time registration. Distinguish desired preferences, helper-reported success, + and independently observed host state; a Boolean success is not an OS read-back guarantee. Startup-registration + success is persisted only after its helper reports success. Settings storage and cached repository objects are distinct lifetimes: changing a QSettings identity does not reconstruct `Storage` backends. Tests that replace settings must isolate both boundaries before exercising cleanup or restoration. - Keep proxy, DNS, routing, TUN, startup registration, session callbacks, external commands, and platform detection here diff --git a/Furious/Interface/AGENTS.md b/Furious/Interface/AGENTS.md index dd900a5..26d44dc 100644 --- a/Furious/Interface/AGENTS.md +++ b/Furious/Interface/AGENTS.md @@ -26,8 +26,9 @@ implementations can satisfy without importing application composition or concret contracts. - Runtime liveness is observational: querying it must not consume an exit, transfer ownership, or dispatch 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. Define - cleanup-failure semantics without assuming every runtime owns a subprocess. Bounded stop/dispose is a contract to + are different facts. Preserve both in terminal events so orchestration can interpret the exit in its current + attempt/connection context without making the runtime own controller policy. Keep semantic startup errors separate + from process codes and readiness timeouts. Define cleanup-failure semantics without assuming every runtime owns a subprocess. Bounded stop/dispose is a contract to verify, not a guarantee supplied by the base class: third-party work may be non-cooperative. Report known violations at their implementation/owner boundary rather than weakening the interface to bless an unreleased resource. - Verify cheap/import-independent contracts plus representative runtime, storage, editor, application-exit, diff --git a/Furious/Models/AGENTS.md b/Furious/Models/AGENTS.md index 8bcc70c..8077b3a 100644 --- a/Furious/Models/AGENTS.md +++ b/Furious/Models/AGENTS.md @@ -34,8 +34,10 @@ never live persistence, Qt presentation, plugin discovery, or workflow execution ## Compatibility and verification -- Protocol construction/export belongs to plugin capabilities. Compatibility shims may remain while callers migrate, - but new protocol-name branches do not belong in core models. +- Protocol construction/export belongs to plugin capabilities. Profile mapping access and `toJSONString()` expose + the connection document, not a complete profile record; persistence must encode metadata explicitly through its + repository contract. A URI is the selected codec's projection. Compatibility shims may remain while callers + migrate, but new protocol-name branches do not belong in core models. - Verify malformed/current/legacy/unknown-field round trips, metadata/connection separation, copy/identity semantics, deterministic fingerprints, construction/serialization diagnostics, and capability-based import/export. Revise this guide with intentional domain changes; do not preserve a legacy identity rule after migration replaces diff --git a/Furious/Plugins/AGENTS.md b/Furious/Plugins/AGENTS.md index 1e3ef08..083457a 100644 --- a/Furious/Plugins/AGENTS.md +++ b/Furious/Plugins/AGENTS.md @@ -52,6 +52,8 @@ remains in each implementation. - Capability instances default to GUI-thread-only for background subscription preparation. A decoder or protocol handler opts into worker execution only after its parsing, validation, caches, globals, and Qt usage are audited as safe for concurrent copied inputs; keep unclassified third-party capability execution on the GUI thread. + `workerSafe` authorizes concurrent execution, not bounded duration or interruptibility. Cancellation can reject a + result while the provider still runs; define resource retention and shutdown separately from that opt-in. ## Verification diff --git a/Furious/Qt/AGENTS.md b/Furious/Qt/AGENTS.md index d76cafd..8d140b9 100644 --- a/Furious/Qt/AGENTS.md +++ b/Furious/Qt/AGENTS.md @@ -49,7 +49,9 @@ behavior, and lifetime primitives; pages and services consume them without creat native destruction/disconnection boundary and both owner-first and sender-first teardown. - Detaching a child ends the shared QObject-tree lifetime assumption. Disconnect the registrations owned by that feature before reparenting, preserve unrelated listeners, and remove default/escape/selection references when the - child dies. `AppQMessageBox` button reuse and native-destruction regressions exercise this boundary. + child dies. Signal delivery is also a reentrancy boundary: a listener may delete the sender or its owner before + the emitting method resumes. Recheck validity before later native calls. `AppQMessageBox` button reuse and + native-destruction regressions exercise both boundaries. - Direct connections are appropriate for deliberately shared persistent lifetimes; syntax alone does not prove a leak. Recheck the selected Nuitka/PySide6 callback protection when the toolchain changes. Static weak method names are runtime contracts, so renames must update registrations and tests. Weak dispatch itself does not marshal diff --git a/Furious/Repository/AGENTS.md b/Furious/Repository/AGENTS.md index eef813b..7212f78 100644 --- a/Furious/Repository/AGENTS.md +++ b/Furious/Repository/AGENTS.md @@ -35,4 +35,6 @@ outside it. - Verify legacy/current/unknown-field round trips, malformed roots, restore-failure preservation, ordering/stable identity, group isolation, reconciliation commit behavior, and persistence in temporary QSettings namespaces. Use `tests/test_repository_contracts.py` and `tests/test_subscription_sync.py` to revalidate this scope. Reordering a - filtered view must preserve hidden slots and relocate activation by profile ID, not by its former row. + filtered view must preserve hidden slots, selected relative order, and unrelated profiles, then relocate activation + by profile ID. Test the complete repository order as well as the visible projection; a correctly painted view can + conceal a wrong persisted ordering. diff --git a/Furious/Service/AGENTS.md b/Furious/Service/AGENTS.md index 509c602..0cd26b1 100644 --- a/Furious/Service/AGENTS.md +++ b/Furious/Service/AGENTS.md @@ -49,9 +49,11 @@ for execution, and Qt for lifetime primitives. This scope owns multi-stage workf revision, commits while preserving live profile identity/local metadata, then publishes coalesced status/structure. Post-commit reconnect/test invalidation failure is reported without undoing committed profiles. This is live reconciliation; repository flush and status persistence are separate boundaries, not one disk transaction. -- User-requested subscription stop invalidates pending generations and marks unfinished groups cancelled. Keep - completed commits/results and automatic update schedules; future updates remain admissible. Logical batch - completion does not release a still-running preparation worker or its relay. +- User-requested subscription stop invalidates pending generations and marks unfinished groups cancelled. Publish + old group cancellation state before aborting replies: abort can synchronously finish a batch whose observers start + another update. Finish only captured old operation contexts, never overwrite a newer generation's status. Keep + completed commits/results and automatic schedules; future updates remain admissible. Logical batch completion + does not release a still-running preparation worker or its relay. - Provider-reported subscription usage/expiry metadata is untrusted advisory input. Parse it with strict bounds at the network boundary and commit or clear it only alongside a successful current synchronization; failed synchronization preserves the last successful metadata. diff --git a/Furious/Utility/AGENTS.md b/Furious/Utility/AGENTS.md index 0ff28a7..3e8d007 100644 --- a/Furious/Utility/AGENTS.md +++ b/Furious/Utility/AGENTS.md @@ -20,8 +20,9 @@ protocol and is not a general-purpose utility bucket. exit result: the flag proves only that a file write completed, not that the child succeeded or the report can be parsed as an exit protocol. Test reporting both with and without a constructed application/log manager. - 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. + report but does not call the ordinary application `run()` initialization. Do not assume plugin, storage, controller, + or main-window initialization occurred merely because the fallback has a Qt application. Keep its constructor + dependencies in failure-path tests and preserve the original result when evolving reporting failures. - Verify normal return, exception, assertion, signal, pre-application failure, crash-log failure, command dispatch, cross-platform spawn, exact child joining, and absence of manager servers or orphaned resources. If this process topology changes intentionally, rewrite this guide rather than layering another supervisor over the old one. diff --git a/Furious/Widget/AGENTS.md b/Furious/Widget/AGENTS.md index 6c934cd..6b0a0a3 100644 --- a/Furious/Widget/AGENTS.md +++ b/Furious/Widget/AGENTS.md @@ -37,8 +37,9 @@ view an independent workflow authority. window parent can outlive the view, and an unparented prompt can outlive both. Native view destruction must end the prompt without running its mutation; `test_qt_lifetime.py` exercises this with the containing window still alive. - 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. + metadata-only test results should update the exact cell. A persistent model index is valid only within its model + and can be invalidated by removal/reset; use domain IDs across collection/model replacement. Do not use resets or + full repaints to mask broken mapping. 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 diff --git a/Furious/Window/AGENTS.md b/Furious/Window/AGENTS.md index a5559eb..5a09b3d 100644 --- a/Furious/Window/AGENTS.md +++ b/Furious/Window/AGENTS.md @@ -29,8 +29,9 @@ state. cleanup path through the containing window/application. Moving a service between pages must not duplicate schedules, histories, requests, or controller connections during the transition. - One-shot editors/prompts use managed transient dialogs and weak compiled-safe continuations. Reusable text/editor - windows and retained settings dialogs need an explicit owner and reopen policy. A settings label or Qt parent does - not determine lifetime: check the actual base class and close/accept/reject path before changing deletion policy. + 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. - 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 dc30bae..8c91f8e 100644 --- a/Icons/AGENTS.md +++ b/Icons/AGENTS.md @@ -8,6 +8,8 @@ resource-manifest contract; it does not govern general UI layout. - 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. + Mask/opacity helpers cache shared icon values: keep cache size bounded and keys independent of widgets, and avoid + mutating a cached icon as if it belonged to one control. - 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 diff --git a/tests/AGENTS.md b/tests/AGENTS.md index 8be1297..409bd05 100644 --- a/tests/AGENTS.md +++ b/tests/AGENTS.md @@ -59,7 +59,9 @@ and test-tier selection; test convenience never weakens a production invariant. 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. + Expected negative-path logs do not themselves mean failure. However, an exception raised inside a Qt-dispatched + callback may reach `sys.excepthook` without failing the surrounding unittest. Reentrant/lifetime tests must also + capture and assert callback exceptions, restoring the hook afterward; a successful runner exit alone is insufficient. - Review new tests for production-state mutation, live network dependence, process-name cleanup, unbounded waits, shared mutable fixtures, order dependence, timing-only assertions, and storage assertions where runtime output is the contract. For guidance-only changes, verify path preservation, changed-file scope, referenced commands/tests,