diff --git a/.github/AGENTS.md b/.github/AGENTS.md index 20c20f9..7ad51c4 100644 --- a/.github/AGENTS.md +++ b/.github/AGENTS.md @@ -46,8 +46,9 @@ exceptions; it does not define the source test suite or imply that every package required dependency of PyPI publication through `workflows/deploy-pypi.yml`. It can also run manually. Daily binary builds retain their separate artifact scope. Source tests do not establish packaged behavior or Python/Qt floors beyond their matrix. Do not call an artifact build a regression-test pass; use `tests/README.md` for - 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 + source verification. The source suite's offscreen Qt environment exercises widgets and event delivery, not native + tray integration, privilege prompts, or an installed application's host effects. 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. Record which workflow invocation and effective dependency set produced an artifact; a passing standalone binary job diff --git a/AGENTS.md b/AGENTS.md index df8c4e9..6752213 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -23,9 +23,9 @@ represent. A new scope never makes an existing one disposable. Keep override files explicit about which inherited assumption they replace and why. - Before a hierarchy-wide audit, inventory tracked, untracked, hidden, and ignored AGENTS paths, including - overrides; record each scope and its nearest ancestor guide. At handoff compare exact path sets and Git - status/diff: no original path may disappear or become a rename. Default to exact equality and improve redundant - scopes in place. + overrides; record each scope, nearest ancestor guide, tracking status, and initial content. At handoff compare + exact path sets and Git status/diff; separately compare ignored/untracked guides that Git's ordinary diff omits. + No original path may disappear or become a rename. Default to exact equality and improve redundant scopes in place. - Inheritance follows directory ancestry. Name the nearest governing guide when clarifying a scope; a sibling guide identifies a contract to consult, not another parent. Verification and self-evolution here apply to every descendant scope without repeating the same maintenance checklist in each file. Ignored comparison checkouts retain their own @@ -128,7 +128,8 @@ - After significant architectural work, re-read the applicable hierarchy as a fresh agent: can it identify the owner, invariant, failure boundary, and relevant tests without relying on conversation history? Challenge rules likely to become stale, circular references, and wording that freezes incidental structure. -- Distinguish requirements, observed implementation, and verified gaps. State the evidence boundary: a test name is an - investigation anchor, not proof that every failure path is covered. Keep run-specific counts, versions, and diagnostic - experiments in the work report; put only durable constraints in guidance. During guidance-only work, report defects - separately instead of changing production code to satisfy the prose. +- Distinguish requirements, observed implementation, and verified gaps. For a claimed guarantee, trace its failure + path as well as its successful caller; a test name is an investigation anchor, not proof of unexercised behavior. + Keep run-specific counts, versions, and diagnostic experiments in the work report; put only durable constraints in + guidance. During guidance-only work, report defects separately instead of changing production code to satisfy + the prose. diff --git a/Furious/AGENTS.md b/Furious/AGENTS.md index 9964e4e..8842f74 100644 --- a/Furious/AGENTS.md +++ b/Furious/AGENTS.md @@ -45,8 +45,10 @@ place. preserve one scheduler, result boundary, and cleanup path. Widgets should not absorb new workflow orchestration. - Plugin registries index process-lifetime plugins, descriptors, and capabilities. Created editors and active runtimes transfer to explicit UI/workflow owners. A capability may own a reusable service, such as asset updating, - but that service still needs a cleanup boundary. Built-ins use the public capability contract; existing - global-access helpers are host integration, not an extra requirement for external plugins. + but that service still needs a cleanup boundary. Capability dispatch does not implicitly clone input or commit + preferences: callers establish isolation and the owning controller/repository establishes mutation. Built-ins use + the public capability contract; existing global-access helpers are host integration, not an extra requirement + for external plugins. - Keep GUI work bounded, cross worker results through the owning Qt thread, and define cancellation/supersession for every asynchronous workflow. Page visibility may control rendering, never ownership of collection or draining. - Preserve unknown/forward-compatible fields through model, repository, backend editor, and serialization changes. diff --git a/Furious/Actions/AGENTS.md b/Furious/Actions/AGENTS.md index 430bd38..03086d7 100644 --- a/Furious/Actions/AGENTS.md +++ b/Furious/Actions/AGENTS.md @@ -12,8 +12,10 @@ owned commands and presentation without becoming a workflow authority. Distinct window/tray contexts may need separate actions that observe the same controller; do not force one global action across incompatible lifetimes. Keep checked/enabled state and translation consistent, and do not make menu shortcuts application-wide when focused editors or other controls own the same keys. -- Routing and connection actions render the shared controllers. Rebuilding a dynamic menu releases the old actions, - action group, and callbacks before publishing the new snapshot; user-defined labels remain untranslated. +- Routing and connection actions render the shared controllers. Rebuilding a dynamic menu retires its old actions + and action group; deferred deletion completes only when Qt processes it. Verify native destruction after repeated + rebuilds rather than treating an emptied Python list as release. Refreshing options is observational, not a user + selection or reconnect command; user-defined labels remain untranslated. - Existing import actions still combine capture/file/clipboard presentation with incremental repository insertion. Treat that as a compatibility path, not a service template. Reuse plugin protocol parsing, construct a complete valid result before each mutation, and keep batched GUI work cancellable and bounded per event-loop turn. diff --git a/Furious/Application/AGENTS.md b/Furious/Application/AGENTS.md index 748248e..e6c81a9 100644 --- a/Furious/Application/AGENTS.md +++ b/Furious/Application/AGENTS.md @@ -11,9 +11,10 @@ boundary between the outer child-process supervisor and the inner application ev dependencies when changing stage order. - 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. + One callback failure does not skip later stages, but the stack consumes that callback and does not retry it. + Its successful `close()` return means this invocation ran the stack, not that every resource was released. + 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 f0c2637..386d509 100644 --- a/Furious/Backends/AGENTS.md +++ b/Furious/Backends/AGENTS.md @@ -22,6 +22,9 @@ generic default. owns the editable snapshot, acceptance validation, identity resolution, and eventual write-back. Runtime factories likewise transfer fresh execution resources to the workflow owner. Editor acceptance and runtime readiness are different validations; neither may silently rewrite stored data to make a later stage succeed. +- `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. ## TUN and runtime policy diff --git a/Furious/Backends/ExternalCore/AGENTS.md b/Furious/Backends/ExternalCore/AGENTS.md index b90883c..667cd6e 100644 --- a/Furious/Backends/ExternalCore/AGENTS.md +++ b/Furious/Backends/ExternalCore/AGENTS.md @@ -28,6 +28,9 @@ preserves the intentionally different direct-subprocess scope for user-selected - Application tun2socks is an explicit profile capability. It requires a usable SOCKS endpoint and a separate remote server address for bypass routing; an executable path is never a network destination, and this backend never invents native core TUN support. Subscription decoding must continue to reject executable profiles. +- 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 the documented timeout gap, rather than assuming a serializable mapping is safe or executable. - This is a mapping-only protocol: its explicit type discriminator selects local executable configuration, it declares no URI schemes, and portable URI/QR export may return no result. Shared import/export UI must preserve that capability absence. Endpoint readiness checks the configured proxy; it does not validate an arbitrary diff --git a/Furious/Backends/Hysteria1/AGENTS.md b/Furious/Backends/Hysteria1/AGENTS.md index f585520..1c085ea 100644 --- a/Furious/Backends/Hysteria1/AGENTS.md +++ b/Furious/Backends/Hysteria1/AGENTS.md @@ -11,8 +11,10 @@ exists to preserve Hysteria 1's legacy flat schema and lifecycle without importi - 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. - 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. + host routing or connection commit. Keep the factory's unsupported routing/TUN combination rejection before + execution acquisition; do not silently substitute Global routing or borrow native TUN from Hysteria 2. + Keep MMDB/ACL launch preparation here and application-TUN acquisition/rollback with that workflow. The existing + rejection prompt is a compatibility path, not a requirement that runtime factories own UI. - 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 cbc1e78..4a403b7 100644 --- a/Furious/Backends/Hysteria2/AGENTS.md +++ b/Furious/Backends/Hysteria2/AGENTS.md @@ -33,6 +33,8 @@ owns Hysteria 2's nested upstream document, native-TUN capability, statistics, a response with no entry for the selected client, which currently represents zero counters. - Capability presence is independent: native TUN, statistics, actions, settings, routing, and protocol editing must continue to work or fail through their own declared contracts rather than being inferred from the runtime type. + This factory does not publish Xray's named/custom routing options. Preserve the no-options case through shared + routing presentation and runtime preparation; a stored routing preference is not evidence of backend support. - Verify nested sibling/default preservation, known and unknown values, obfuscation switching, URI/document projection preservation, every native/application-TUN and resolution case, probe stripping, readiness/exit cleanup, statistics cancellation, and repeated transient editor/settings-dialog destruction. Keep this guide synchronized with diff --git a/Furious/Backends/Xray/AGENTS.md b/Furious/Backends/Xray/AGENTS.md index 925e6e5..7677113 100644 --- a/Furious/Backends/Xray/AGENTS.md +++ b/Furious/Backends/Xray/AGENTS.md @@ -37,8 +37,14 @@ owns Xray's full JSON preservation, routing/assets/statistics, and protocol/tran 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. + and repository/runtime order round trips. Confirmations within a rules editor share that transient dialog's Qt + lifetime; the reconnect notice after editor completion belongs to the surviving routing table instead. +- The rules editor mutates the live routing document; closing/rejecting it is not rollback. Compare net rule changes + against the snapshot captured after model normalization and verify the same document still occupies the captured + routing ID before notifying. Reverted/no-op edits and replaced/deleted targets do not notify. Reordering is a rule + change, but the notice occurs at editor completion, not on each move. `RoutingChangeNoticeTest` in + `tests/test_ui_behavior.py` covers this boundary. Its connected/selected-route predicate must not be mistaken for + proof of the running core's routing after a declined reconnect. - 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 f6d05fb..b4f3572 100644 --- a/Furious/Controllers/AGENTS.md +++ b/Furious/Controllers/AGENTS.md @@ -30,6 +30,9 @@ compatibility paths. otherwise the repository's activated profile. Normalizing the displayed option does not itself persist a new preference; explicit selection or invalidation owns that mutation. Disabling the selected custom route persists its supported fallback without reconnecting by itself; re-enabling restores availability, not selection. + If reconnect is declined, selected/persisted routing may differ from the running document. Menu checkmarks prove + selection only; exercise fallback persistence separately from reconnect acceptance and runtime preparation. + `RoutingControllerTest` in `tests/test_controllers.py` anchors explicit invalidation versus observational refresh. User-defined routing labels are not translatable UI literals. - `SettingsController` is the shared policy path used by Home, Settings, tray, and platform integration. Startup registration persists only after host success; other preferences may apply immediately or on the next connection. diff --git a/Furious/Core/AGENTS.md b/Furious/Core/AGENTS.md index 0684371..5611046 100644 --- a/Furious/Core/AGENTS.md +++ b/Furious/Core/AGENTS.md @@ -29,7 +29,9 @@ connection policy remains outside it. - Child targets never touch Qt widgets. Output transport is non-blocking and bounded in message size, pending volume, and per-turn drain work; draining continues independently of Log-page visibility and backs off only when idle. Diagnostic output may be truncated or dropped under pressure, so it cannot be the authoritative terminal-event channel. Preserve - typed exit delivery independently of log transport and rendering. + typed exit delivery independently of log transport and rendering. The output callback runs at the GUI drain + boundary, so bounding queue admission alone is insufficient: preserve bounded drain batches and a bounded consumer + such as the shared log model. Test producer pressure and hidden-page draining independently. - Parentless timers are acceptable only with a durable runtime owner and explicit disposal. Leaving the manager pool must not leave timers, callbacks, queues, or process handles alive. Stopping execution is not QObject destruction: disposal must also release monitors and output infrastructure, including for a runtime that was never started. diff --git a/Furious/Data/AGENTS.md b/Furious/Data/AGENTS.md index 12201c6..9e14e97 100644 --- a/Furious/Data/AGENTS.md +++ b/Furious/Data/AGENTS.md @@ -19,7 +19,9 @@ provenance; it is not an application-data or settings directory. ## Local endpoint map -- MapLibre JavaScript/CSS and the host bridge are bundled; the style requests vector tiles and glyphs from +- Keep vendored `maplibre-gl.js`/CSS and their license distinct from the application-owned `EndpointMap.js`/HTML + bridge. Change host behavior in the bridge and its Python consumer; a vendor replacement needs separate provenance + and compatibility review. The style requests vector tiles and glyphs from `tiles.openfreemap.org`. This is not an offline map. Keep executable code local, preserve attribution, and review the HTML content-security policy and the widget's attribution-link validation when changing network resources or links. Missing tiles/network detail must degrade without crashing the renderer or the application. diff --git a/Furious/Extensions/AGENTS.md b/Furious/Extensions/AGENTS.md index 02273ac..45bd5e2 100644 --- a/Furious/Extensions/AGENTS.md +++ b/Furious/Extensions/AGENTS.md @@ -23,7 +23,9 @@ is bundled. 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 boundaries. Test recognized-empty, wholly unsupported, and mixed-validity payloads separately so decoder matching is not - confused with successful profile import or authorization to clear an existing group. + confused with successful profile import or authorization to clear an existing group. The standard share-link + decoder treats blank/comment-only content as a mismatch; an empty result from a different decoder needs its own + import/reconciliation policy, not an assumption borrowed from this format. - Keep bundled registration deterministic, side-effect-light, and discoverable in source, wheel, and Nuitka builds. Test format selection/fallback, malformed and secret-bearing input, duplicate occurrence identity, unsupported subscription protocols, registration rollback, and absence of repository/UI mutation during decoding. Evolve this diff --git a/Furious/Externals/AGENTS.md b/Furious/Externals/AGENTS.md index 453fb2f..2e2a7b3 100644 --- a/Furious/Externals/AGENTS.md +++ b/Furious/Externals/AGENTS.md @@ -29,8 +29,9 @@ structure and human-reviewed translations. ## Extractable source text - `_()` normally receives one static literal. The only supported dynamic form is an f-string composed solely of bare - names imported from `Furious.Frozenlib.Constants`; ordinary placeholders, attributes, calls, conversions, format - specifications, concatenation helpers, and `.format()` are not extractable. + names imported from `Furious.Frozenlib.Constants`; runtime expressions, attributes, calls, conversions, format + specifications, and concatenation helpers inside that argument are not extractable. A static literal containing + brace placeholders is extractable: translate it first, then interpolate with `.format()` outside `_()`. - Keep runtime interpolation outside the translatable expression. Translate UI language, not identifiers, protocol values, user-defined names, persisted values, paths, or diagnostic payloads. - When a control stores source text for later retranslation, update that source instead of manually translating one diff --git a/Furious/Frozenlib/AGENTS.md b/Furious/Frozenlib/AGENTS.md index f5882de..055beed 100644 --- a/Furious/Frozenlib/AGENTS.md +++ b/Furious/Frozenlib/AGENTS.md @@ -20,7 +20,8 @@ boundaries, not a license for unrelated application orchestration to accumulate - Check each helper's real result contract. System Proxy set/off/pac return True for reported host success, False for failure, and None when policy deliberately leaves host settings unchanged. Startup registration and some routing helpers return Booleans; script-mode startup registration intentionally does nothing. Preserve these distinctions - at callers instead of treating absence of an exception as confirmed host state. Check every native command result, + at callers instead of treating absence of an exception as confirmed host state. A skipped (`None`) operation must + not be presented as either a failed mutation or verified host configuration. Check every native command result, including each enabled macOS network service, and bound host-command waits at this boundary. A per-command timeout is not a deadline for a loop over services or routes. Multi-step host mutation may be partial when a later command fails; a False result does not establish that earlier effects were rolled back. diff --git a/Furious/Interface/AGENTS.md b/Furious/Interface/AGENTS.md index 26d44dc..d6a87a2 100644 --- a/Furious/Interface/AGENTS.md +++ b/Furious/Interface/AGENTS.md @@ -21,9 +21,11 @@ implementations can satisfy without importing application composition or concret - `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. -- `ApplicationRunner.ExitCode` is a process-boundary protocol. Model encoders may raise, while configuration - construction deliberately captures diagnostics; do not impose one blanket exception convention on those different - contracts. +- `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. +- Model encoders may raise, while configuration construction deliberately captures diagnostics. Callers must inspect + the contract they consume; successful construction alone proves neither serialization nor backend acceptance. - 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. Preserve both in terminal events so orchestration can interpret the exit in its current diff --git a/Furious/Models/AGENTS.md b/Furious/Models/AGENTS.md index 8077b3a..65bf8c1 100644 --- a/Furious/Models/AGENTS.md +++ b/Furious/Models/AGENTS.md @@ -27,7 +27,9 @@ never live persistence, Qt presentation, plugin discovery, or workflow execution answer different questions. Fingerprints cover only the connection document, not user metadata; they require deterministic JSON-compatible values and reject non-finite numbers. A metadata edit need not invalidate connection testing. Equal fingerprints do not imply equal profile IDs: independently stored profiles may describe identical - connections. Do not merge their metadata, ownership, or selection merely to deduplicate execution work. + connections. A fingerprint also cannot distinguish an old request from a newer request for the same document; + workflow generation/cancellation remains the caller's responsibility. Do not merge metadata, ownership, or + selection merely to deduplicate execution work. - Subscription membership (`subscriptionSource`) and remote ownership (`subscriptionManaged` plus its matching key) are separate. Legacy migration may infer ownership where the flag was absent; current locally grouped profiles must remain local. Preserve that distinction through copies, moves, and metadata aliases. diff --git a/Furious/Plugins/AGENTS.md b/Furious/Plugins/AGENTS.md index 083457a..16b310a 100644 --- a/Furious/Plugins/AGENTS.md +++ b/Furious/Plugins/AGENTS.md @@ -47,8 +47,10 @@ remains in each implementation. log and return an unhandled result; required TUN rejection must use the typed error rather than assume all exceptions stop fallback. Optional capabilities may be absent; an External Core need not implement statistics or download probes. -- Frozen result envelopes are not recursively immutable: embedded configuration/metadata mappings still require copy - isolation before mutation or worker handoff. +- Frozen request/result envelopes are not recursively immutable: embedded configuration/metadata mappings still + require copy isolation before mutation or worker handoff. `createCoreRuntime()` dispatches preparation to a factory; + it does not protect live configuration from that factory's mutations. Routing normalization chooses a supported + option but does not persist it; that decision belongs to the routing controller. - 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. diff --git a/Furious/Qt/AGENTS.md b/Furious/Qt/AGENTS.md index 8d140b9..dab7fe4 100644 --- a/Furious/Qt/AGENTS.md +++ b/Furious/Qt/AGENTS.md @@ -57,7 +57,9 @@ behavior, and lifetime primitives; pages and services consume them without creat are runtime contracts, so renames must update registrations and tests. Weak dispatch itself does not marshal arbitrary worker calls to the GUI thread; choose an explicit queued owner-thread delivery boundary. A surviving Python wrapper can already be natively invalid, so callback freshness and `shiboken6.isValid()` address different - failure modes. Neither replaces the strong owner required while asynchronous UI remains active. + failure modes. Neither replaces the strong owner required while asynchronous UI remains active. For independent + sender/receiver trees, test both destruction orders: receiver cleanup must disconnect its edge, and sender cleanup + must retire receiver-side tracking without keeping a signal wrapper or sender alive. - `AppQAction.callback` is strong by design, so its owner must not outlive the captured receiver; construction alone does not enforce that requirement. An action also owns a submenu supplied without a QWidget parent and schedules its native deletion when the action dies; diff --git a/Furious/Repository/AGENTS.md b/Furious/Repository/AGENTS.md index 7212f78..0388e12 100644 --- a/Furious/Repository/AGENTS.md +++ b/Furious/Repository/AGENTS.md @@ -18,7 +18,9 @@ outside it. fallback; only an explicit successful replacement may do so. Root decoding, individual-record hydration, and later serialization are separate failure boundaries. Test malformed records inside a valid root as well as malformed roots. Profile and subscription hydration publishes only a complete collection; an invalid record must not - expose a partially restored prefix that cleanup can serialize over the original document. + expose a partially restored prefix that cleanup can serialize over the original document. The restore-failure + guard protects automatic cleanup, not an arbitrary explicit `sync()` call. Do not flush an empty fallback merely + to inspect or acknowledge a load failure; test the original persisted bytes through the cleanup path. - Stage fallible decode/migration before live mutation. Subscription reconciliation currently belongs to `Furious/Service/SubscriptionSync.py` and commits through the compatibility live collection: matched managed profiles retain object/profile identity and local metadata, removed profiles become stale, and unrelated groups remain diff --git a/Furious/Service/AGENTS.md b/Furious/Service/AGENTS.md index 0cd26b1..7f2879a 100644 --- a/Furious/Service/AGENTS.md +++ b/Furious/Service/AGENTS.md @@ -19,7 +19,8 @@ for execution, and Qt for lifetime primitives. This scope owns multi-stage workf identity rejects stale completion. Successful release is idempotent; failed drains may require retry while their owner remains alive, without publishing another terminal result. Delete replies/Qt objects in their owning thread and release contexts only when execution no longer needs them. Late delivery must not revive a shut-down manager - or mutate live state. + or mutate live state. A terminal result ends an operation's publication contract, not necessarily its execution: + a replacement may be admitted only under the scheduler's resource bounds while cancelled work still occupies a slot. ## Connection and network workflows @@ -45,8 +46,9 @@ for execution, and Qt for lifetime primitives. This scope owns multi-stage workf unclassified plugin parsers stay on the GUI compatibility path. The manager's synchronous shutdown closes admission, cancels work, and retains the pool/relay until workers finish. A slow-shutdown warning is diagnostic, not a deadline that permits destroying running workers; a non-returning plugin can still block shutdown. - Workers never read live repositories or Qt models. The GUI thread verifies the full source signature and group - revision, commits while preserving live profile identity/local metadata, then publishes coalesced status/structure. + Subscription preparation workers never read live repositories or Qt models. The GUI thread verifies the full source + signature and group revision, commits while preserving live profile identity/local metadata, then publishes + coalesced status/structure. Post-commit reconnect/test invalidation failure is reported without undoing 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. Publish diff --git a/Furious/Utility/AGENTS.md b/Furious/Utility/AGENTS.md index 3e8d007..782226f 100644 --- a/Furious/Utility/AGENTS.md +++ b/Furious/Utility/AGENTS.md @@ -20,7 +20,8 @@ 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. Do not assume plugin, storage, controller, + report but does not call the ordinary application `run()` initialization. Treat this as a separate composition + path in tests, not a second attempt to restore the user's connection. 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, diff --git a/Furious/Widget/AGENTS.md b/Furious/Widget/AGENTS.md index 6b0a0a3..44c0123 100644 --- a/Furious/Widget/AGENTS.md +++ b/Furious/Widget/AGENTS.md @@ -22,6 +22,8 @@ view an independent workflow authority. keep their own shortcut semantics. Selection identity, current keyboard index, and selection painting are separate: keeping targets highlighted while a command button/menu has focus must not change selection or steal editor focus. Exercise the button-focus interval before popup display as well as the open menu to catch highlight flicker. + An action shared with a page button still resolves the table's selected domain targets when triggered; moving its + presentation must not introduce another test scheduler or a second selection model. ## Workflow and lifetime boundaries diff --git a/Furious/Window/AGENTS.md b/Furious/Window/AGENTS.md index 5a09b3d..20abee4 100644 --- a/Furious/Window/AGENTS.md +++ b/Furious/Window/AGENTS.md @@ -8,6 +8,9 @@ state. - `MainWindow` owns the persistent built-in page tree and navigation; plugin pages enter through the plugin navigation service. Pages adapt shared controllers/services/repositories and must not become competing state authorities. + Plugin page factories transfer widgets to the navigation owner; the registry's lifetime does not keep a page valid. + Verify failed construction/registration cleanup as well as successful one-time registration through + `PluginNavigationManager` and `tests/test_service_runtime.py`. Preserve application-facing forwarding APIs until their consumers migrate deliberately. Bulk profile forwarding must retain the bulk mutation boundary through Home and its model, without expanding into per-profile refreshes. - Home, Settings, tray actions, and reusable dialogs render the same connection, routing, and settings controllers. diff --git a/Icons/AGENTS.md b/Icons/AGENTS.md index 8c91f8e..1927146 100644 --- a/Icons/AGENTS.md +++ b/Icons/AGENTS.md @@ -19,6 +19,8 @@ resource-manifest contract; it does not govern general UI layout. replacement so an apparently unused file is not removed while still generated or consumed through an alias. Selecting an already bundled Bootstrap icon normally changes its consumer only; it does not require regeneration or another SVG copy. Compare the glyph's visible bounds at the actual control size, not only its nominal SVG canvas. + An icon substitution preserves the command's accessible text, shortcut, checked state, selection target, and + popup-focus behavior. Verify those semantics at the consumer rather than imposing a new action-construction pattern. - Verify alias uniqueness and source/package resolution, then inspect the actual control or tray use under both themes, high DPI, relevant sizes, disabled/selected states, and platform packaging where applicable. Deployment icons also have direct filesystem consumers in `Deploy.py`; a resource alias search alone cannot prove a PNG is diff --git a/tests/AGENTS.md b/tests/AGENTS.md index 409bd05..1bdd8a4 100644 --- a/tests/AGENTS.md +++ b/tests/AGENTS.md @@ -24,6 +24,9 @@ and test-tier selection; test convenience never weakens a production invariant. counters/registries are valid evidence when ownership, reclamation, or complexity is the contract; pair them with an observable result instead of treating every implementation detail as forbidden. Cover success, invalid input, timeout/cancel, stale/partial completion, rollback, cleanup, and compatible persisted input where applicable. +- 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. - 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,