Evolve repository guidance

Signed-off-by: Loren Eteval <loren.eteval@proton.me>
This commit is contained in:
Loren Eteval
2026-09-08 10:54:14 +08:00
parent 680ebfc16b
commit bd24ff3085
26 changed files with 157 additions and 5 deletions
+16 -4
View File
@@ -11,7 +11,17 @@
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
evolution, compatibility debt, or a bug; preserve the intended invariant and update either code or the narrowest
applicable guidance. Do not encode speculation, experiments, or incidental class names as durable rules.
applicable guidance. Never resolve the contradiction by deleting the scoped guidance file. Do not encode speculation,
experiments, or incidental class names as durable rules.
## Preserve the guidance hierarchy
- Every existing `AGENTS.md` and `AGENTS.override.md` path is an established documentation scope. During ordinary
guidance maintenance, do not delete, rename, relocate, merge, consolidate, or change the kind of any existing file.
Improve a seemingly redundant scope in place by making its inherited and local rules more precise.
- Add a new AGENTS file only when verified architecture has a durable uncovered scope that no existing file can
represent. A new scope never makes an existing one disposable. Keep override files explicit about which inherited
assumption they replace and why.
## Operating model
@@ -81,11 +91,13 @@
## Maintaining this guidance
- AGENTS files contain durable decision rules, not inventories or frozen recipes. Update guidance only when supported by
- AGENTS files are maintained architectural memory, not immutable truth. Update durable rules only when supported by
current architecture, tests, verified runtime behavior, explicit design, or an intentional refactor completed in the
same change.
- Put a rule at the narrowest scope where it helps future decisions; let child guides specialize rather than repeat
parents. Remove obsolete rules and distinguish preferred architecture from compatibility paths.
parents. Remove obsolete content inside files, distinguish preferred architecture from compatibility paths, and
preserve every established file path while doing so.
- After significant architectural work, ask what durable fact was learned, whether guidance now misleads, and whether a
future agent would choose the correct owner and test boundary. Do not update AGENTS for temporary implementation
future agent would choose the correct owner and test boundary. Re-read the applicable hierarchy as a fresh agent,
challenge rules most likely to become stale or freeze implementation, and do not record temporary implementation
details.
+5 -1
View File
@@ -1,5 +1,8 @@
# Furious package guidance
Inherit repository-wide rules from the root `AGENTS.md`. This file preserves the package-level boundary between
domain, persistence, orchestration, platform integration, and presentation; nested guides specialize it in place.
## Responsibility boundaries
- `Application` is the composition root. Elsewhere depend on the narrowest model, repository, service, controller, or
@@ -49,4 +52,5 @@
- Read the applicable specialized guide for application composition, embedded core processes, platform helpers,
repositories, plugins, services, backends, Qt ownership, translations, or bundled data. A missing child guide means
this file and the root guide are sufficient; do not recreate one merely to restate them.
this file and the root guide are sufficient; do not recreate one merely to restate them. Existing child guides are
established scopes: clarify inheritance or local invariants rather than deleting or consolidating them.
+6
View File
@@ -1,5 +1,8 @@
# Action guidance
Inherit the root and `Furious/AGENTS.md`; this scope adds rules for translating user gestures into owned commands and
presentation without becoming a workflow authority.
## Command boundary
- Actions adapt one user command to presentation. Resolve live controller/repository state when triggered, delegate the
@@ -20,6 +23,9 @@
transient/repeated receiver uses the weak named-method facilities required by `Furious/Qt/AGENTS.md`.
- Clipboard text, files, QR images, share links, and plugin results are untrusted and may contain credentials. Bound
diagnostic excerpts and never log or echo a complete secret-bearing payload merely to explain a parse failure.
- Long-running capture/import/export presentation owns one cancellable operation context. Yield large GUI insertions or
QR rendering in bounded event-loop batches, reject callbacks after cancellation/destruction, and publish output only
while the operation context and its owned snapshot remain current.
- Verify command state and delegation, cancellation/error presentation, shortcut scope in the real focused widget, menu
rebuild cleanup, and repeated dialog/capture/action lifetimes. When this command boundary changes intentionally, update
this guide and remove superseded compatibility wording in the same change.
+6
View File
@@ -1,11 +1,17 @@
# Application composition guidance
Inherit the root and package guides. This scope owns process-lifetime Qt composition and the boundary between the outer
child-process supervisor and the inner application event loop.
- `Furious.__main__` and `AppMainProcess` own the outer process/crash boundary; `DesktopApplication` owns the inner Qt
composition. Keep those responsibilities separate and preserve semantic exit codes and original failure context.
- Startup acquires singleton ownership before composing process-lifetime repositories, plugins, controllers, logging,
host integration, UI, and optional restored connection. Register cleanup as each acquisition succeeds.
- Partial startup, normal exit, signals, and event-loop failure converge on one reverse-order, failure-isolating,
idempotent cleanup path. `exit()` requests Qt termination; action/window/session handlers do not run cleanup directly.
- Register cleanup immediately after each successful acquisition, before the next fallible stage. Cleanup code must
tolerate a partially composed application and must not assume later repositories, controllers, UI, tray, or host
integration were created.
- Singleton election is atomic: serialize candidates, re-probe after waiting, recover only a confirmed stale endpoint,
and fail closed when ownership is uncertain, including privilege handoff.
- Native session callbacks cross to the GUI thread before touching Qt-owned state. Tray, dock, System Proxy daemon,
+6
View File
@@ -1,5 +1,8 @@
# Backend guidance
Inherit the root, package, plugin, model, and service contracts. This scope adds rules shared by all bundled proxy
backends without making the richest backend the generic default.
## Common backend contract
- A backend plugin owns its configuration/document types, parsing/export, validation, editor factories, runtime factory,
@@ -24,6 +27,9 @@
than permission to silently switch implementations.
- A runtime owns its exact process/thread/readers/monitors and publishes an actionable start error. Stop/dispose is
bounded, idempotent, and correct after partial acquisition.
- Runtime factories follow the current plugin contract: fully prepare and return one owned launch whose zero-argument
start is separate from readiness observation. Do not hide readiness waits, Boolean success channels, or controller
policy inside a backend runtime.
## Backend scopes
+5
View File
@@ -1,5 +1,8 @@
# External Core guidance
Inherit the backend and plugin rules. This file preserves the intentionally different direct-subprocess scope for
user-selected executables.
## Structured executable boundary
- External Core represents one user-selected local executable, not an embedded protocol binding. Keep executable path,
@@ -15,6 +18,8 @@
- One runtime owns its exact `Popen`, stdout/stderr pipes and readers, watcher, partial-line buffer, exit callback, and
reaping path. Shutdown terminates that process, uses only platform-specific escalation for its PID when necessary,
kills as a last resort, joins readers, and remains bounded and idempotent after partial startup.
- Keep execution liveness, configured proxy endpoints, and semantic readiness distinct. An immediate or later exit is
interpreted once at this runtime boundary and retains actionable code/reason context for the shared startup workflow.
- 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.
+5
View File
@@ -1,5 +1,8 @@
# Hysteria 1 guidance
Inherit the common backend and plugin rules. This scope exists to preserve Hysteria 1's legacy flat schema and lifecycle
without importing assumptions from Hysteria 2.
- Hysteria 1 is the legacy flat client schema and `hysteria://` share-link backend. Do not import Hysteria 2 nested
documents, obfuscation, statistics, realm, or native-TUN semantics merely because the upstream names are related.
- Preserve tolerated legacy types, upstream field names, absent defaults, and unknown combo values. Loading and an
@@ -10,6 +13,8 @@
- 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 backends policy.
- Treat tolerated legacy values as input compatibility, not as permission to rewrite the persisted document during
inspection. Runtime validation may reject what observational editor loading must still preserve.
- 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. Revise this guide with an intentional schema evolution instead of freezing quirks.
+5
View File
@@ -1,5 +1,8 @@
# Hysteria 2 guidance
Inherit the common backend and plugin rules. This scope owns Hysteria 2's nested upstream document, native-TUN
capability, statistics, and editor projection.
## Native document and editor projection
- The persisted Hysteria 2 client document is authoritative and is submitted to the embedded runtime. The GUI is a
@@ -17,6 +20,8 @@
backends privilege and server-route-exclusion guarantees. Probe/download copies always remove native TUN.
- Traffic-statistics targets, setting descriptors, and action providers are process-lifetime plugin capabilities;
monitors, replies, dialogs, and runtimes created from them are request/transient objects and are never registry-owned.
- Capability presence is independent: native TUN, statistics, actions, settings, routing, and protocol editing must
continue to work or fail through their own declared contracts rather than being inferred from the runtime type.
- Verify nested sibling/default preservation, known and unknown values, obfuscation switching, URI/document equality,
every native/application-TUN and resolution case, probe stripping, readiness/exit cleanup, statistics cancellation,
and repeated transient editor/settings-dialog destruction. Keep this guide synchronized with verified upstream schema
+5
View File
@@ -1,5 +1,8 @@
# Xray guidance
Inherit the common backend and plugin rules. This scope owns Xray's full JSON preservation, routing/assets/statistics,
and protocol/transport/TLS projections.
## Full-document preservation
- The complete Xray JSON document is authoritative. Protocol, transport, TLS, local-endpoint, logging, routing, and TUN
@@ -20,6 +23,8 @@
- Xray owns routing profiles/options, geo assets, API statistics, and the `XRAY_LOCATION_ASSET` environment contract.
Asset replacement remains digest-verified and atomic; action providers retain reusable routing/asset windows only
through the created action owner and create transient settings dialogs per request.
- Asset downloads stage bytes and digest verification before replacing the live file. A failed request, checksum, or
write leaves the prior usable asset intact and reports the failure without pretending an update succeeded.
- Verify full-document and URI preservation, aliases and unknown values, runtime-copy isolation for routing/log/TUN/tests,
multiple TUN inbounds, asset integrity/failure, statistics and process cleanup, compiled-safe UI callbacks, and
repeated editor/window destruction. Update this scope when an upstream or plugin capability changes intentionally.
+6
View File
@@ -1,5 +1,8 @@
# Controller guidance
Inherit the root and package guides. This scope preserves controllers as process-lifetime authorities for shared
transitions, not owners of execution resources or presentation objects.
## Shared state authorities
- Controllers own process-lifetime shared state and transition policy. They coordinate injected repositories/services
@@ -10,6 +13,9 @@
- Preserve state and signal ordering, interaction gating, the exact selected `ServerProfile`, runtime snapshots,
reconnect preference, and rollback after validation, runtime, TUN, System Proxy, cancellation, or unexpected-exit
failure. Worker/native callbacks cross to the controllers Qt thread before transition.
- A startup completion must belong to the current controller generation before it can change state, active profile,
System Proxy, or interaction gating. Typed runtime failures keep their semantic reason; cancellation and supersession
are not rewritten as generic connection errors.
- `RoutingController` owns available capability options plus selected/persisted routing. Distinguish a newly selected
repository profile from the profile snapshot already owned by a live connection; changes use controlled reconnect,
not mutation of the running document. User-defined routing labels are semantic data, not translatable UI literals.
+6
View File
@@ -1,10 +1,16 @@
# Embedded runtime guidance
Inherit the root, package, interface, and service rules. This scope owns reusable embedded execution machinery and
application tun2socks, while connection policy remains outside it.
- `Core` supplies shared multiprocessing runtime machinery, bounded output transport, and application tun2socks. External
Core owns its separate direct `subprocess.Popen`; neither layer owns controller, repository, UI, or protocol policy.
- A launch spec describes only validated child construction, never semantic connection readiness. Runtime preparation
completes before construction; the asynchronous connection transaction observes endpoints/process survival and
commits later. Keep any synchronous waiting isolated as an explicit compatibility path.
- `CoreRuntime` execution state, typed terminal exit, and readiness are separate contracts. A process becoming alive is
not proof that its proxy/TUN endpoint is ready, while a readiness timeout must not overwrite an already observed typed
exit.
- A runtime owns and reaps its exact child, process handle, monitor/drain timers, queues, callbacks, and feeder resources.
Stop is bounded, escalates only that child when needed, closes handles, and is safe after partial start or repetition.
- Process-backed runtimes monitor and reap their own child, interpret a raw exit exactly once, and publish one typed exit
+3
View File
@@ -1,5 +1,8 @@
# Bundled runtime data guidance
Inherit the root and package guides. This scope exists for shipped runtime assets and their provenance; it is not an
application-data or settings directory.
## Boundary and provenance
- This directory ships application assets, not user state: Xray GeoIP/geosite data, Hysteria MMDB/ACL data, the local
+6
View File
@@ -1,5 +1,8 @@
# Bundled extension guidance
Inherit the root, package, and plugin guides. This scope covers host-shipped non-runtime plugins and must not gain
private authority merely because the code is bundled.
- `Extensions` contains host-shipped plugins that are not proxy runtimes. They register through the same public API and
lifecycle as entry-point plugins and receive no private repository, controller, or UI side channel.
- `StandardSubscriptionPlugin` owns format recognition and decoding only. A decoder returns an immutable neutral
@@ -9,6 +12,9 @@
declared result shape, preserve useful names/upstream IDs, and never log a complete payload or link. Current standard
formats are linear plain/Base64 share-link envelopes; introduce explicit size/depth/work limits before adding richer
recursive or nested formats.
- Decoder output is descriptive, not a repository transaction. It cannot assign live profile identity, mutate a
subscription group, cancel tests, reconnect, or publish UI state; those decisions remain at the import/manager commit
boundaries.
- 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
+5
View File
@@ -1,5 +1,8 @@
# Translation catalog guidance
Inherit the root and package guides. This scope preserves the split between extracted catalog structure and
human-reviewed translations.
## Source and generation contract
- `Furious/Externals/GenTranslation.py` is generator-managed, but its language values and `isReviewed` flags are curated
@@ -28,3 +31,5 @@
- Run extraction for every affected language, review collisions/stale removal/order and the catalog diff, then run it a
second time to prove stability. Exercise runtime lookup and affected UI retranslation under explicit locales.
- Translation generation is a scoped repository mutation: do not run it as an incidental formatter, and do not accept
broad catalog churn without tracing each changed source literal or intentional stale-key removal.
+6
View File
@@ -1,5 +1,8 @@
# Platform and compatibility guidance
Inherit the root and package guides. This scope contains compatibility and host-integration boundaries, not a license
for unrelated application orchestration to accumulate in a broad helper namespace.
- `Frozenlib` is the low-level settings, platform, compatibility, and broad export surface. Keep imports cheap,
cross-platform, and free of application/UI construction; preserve curated wildcard exports until consumers and
public-import tests migrate together.
@@ -11,6 +14,9 @@
- Keep proxy, DNS, routing, TUN, startup registration, session callbacks, external commands, and platform detection here
or behind a runtime boundary so tests can replace them completely. Windows, macOS, Linux, Flatpak, AppImage, and older
platform paths are distinct capabilities; never generalize from the current host.
- A host mutation returns success only after the actual platform operation completed. The owning controller/service
decides rollback and persistence; low-level helpers do not silently update shared UI state or convert an unsupported
platform into a successful no-op.
- Prefer argument vectors over shell strings. Each caller owns any responsiveness/cleanup timeout appropriate to its
context; build-time commands and GUI-time host mutation do not share one universal timeout policy.
- Own exact native threads/processes/handles and clear stale daemon references. Externally keyed caches are bounded and
+6
View File
@@ -1,11 +1,17 @@
# Interface guidance
Inherit the root and package guides. This file preserves dependency-light contracts that multiple implementations can
satisfy without importing application composition or concrete backends.
- This package defines dependency-light contracts shared across layers. It does not import Qt presentation,
controllers, services, repositories, plugins, or concrete backends; a contract may depend on a small model/constant
only when that does not trigger application construction or registration.
- Contracts specify observable ownership, lifecycle, mutation, serialization, callback, and failure semantics. Search
every representative implementation and contract test before changing one; an implementation may strengthen a
guarantee but cannot silently weaken it.
- Keep versioned contract changes explicit. Reject unsupported shapes at the registration/boundary layer, update every
bundled implementation and compatibility export together, and avoid adapters that let two conflicting ownership
models coexist indefinitely.
- `CoreRuntime` is mechanism-neutral: embedded multiprocessing, direct `subprocess`, or an in-process binding can satisfy
it. It owns execution only: zero-argument start, passive liveness, typed terminal events, and bounded idempotent
stop/dispose. Preparation, serialization, readiness, and startup transactions belong outside this contract. Bind its
+6
View File
@@ -1,5 +1,8 @@
# Model guidance
Inherit the root and package guides. This scope owns dependency-light domain shape and identity, never live persistence,
Qt presentation, plugin discovery, or workflow execution.
## Domain shape and identity
- Models are core-neutral Python data and transformations. Do not import Qt, globals, repositories, services,
@@ -11,6 +14,9 @@
subscription ownership/key, latency, speed, annotations, and local flags never become core-configuration fields.
- Preserve unknown metadata and legacy aliases across load/save. `independentCopy()` creates a manual profile with a new
ID and no subscription owner; a runtime `deepcopy()` preserves identity while isolating mutable preparation.
- 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.
- `ensureProfile()` normalizes rather than clones: metadata arguments update an existing profile. Use an independent
copy for a new stored item and a runtime copy when logical identity must survive without mutating persistence.
- Profile ID, object identity, subscription source/key, connection fingerprint, display text, and row position answer
+6
View File
@@ -1,5 +1,8 @@
# Plugin guidance
Inherit the root, package, and interface guides. This scope owns capability definitions, atomic registration, dispatch,
and plugin lifecycle; concrete backend policy remains in each implementation.
## Contracts and registry
- `Plugins.API` defines independently composable capabilities for protocols/editors, subscription decoding, runtime
@@ -25,6 +28,9 @@
entry-point plugins; do not give bundled code hidden repository/UI side channels.
- Evolve contracts additively when practical. Before a breaking change, inspect external discovery, compatibility
exports, every bundled implementation, tests, and compiled inclusion; do not infer compatibility from built-ins alone.
- A capability contract is generic only when an external plugin can satisfy it without importing private application
state. Backend-specific defaults, settings keys, document branches, and host assumptions stay behind the provider
rather than becoming undeclared registry requirements.
- API-version-3 runtime factories return `PreparedRuntime` directly. The runtime is fully prepared before return,
starts with zero arguments, raises typed startup failures, and exposes readiness separately; do not add legacy launch
adapters, Boolean startup side channels, or alternate factory-result shapes.
+5
View File
@@ -3,6 +3,9 @@
Use the `manage-qt-pyside6-lifetimes` skill for QObject ownership, transient/reusable UI, signal retention, or packaged
PySide6 lifetime work.
Inherit the root and package guides. This scope owns reusable Qt presentation, translation/theme behavior, and lifetime
primitives; pages and services consume them without creating parallel registries.
## Canonical presentation
- Reuse `Furious.Qt` `AppQ*` controls, `AppStyleSheet`, translation/theme mixins, and shared dialog/window infrastructure.
@@ -37,6 +40,8 @@ PySide6 lifetime work.
intentional. `AppQAction.callback` is strong by design, so the action owner cannot outlive the captured receiver.
- Every `QNetworkReply` has one manager/context owner, one freshness rule, and one terminal deletion path. Do not attach
ad-hoc attributes to third-party Qt objects or multiply timers/connections across show/hide cycles.
- 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.
## Geometry and verification
+5
View File
@@ -1,5 +1,8 @@
# Repository guidance
Inherit the root, package, interface, and model guides. This scope owns restoration, migration, ordering, and durable
collection commits; workflows and presentation remain outside it.
- Repositories restore, migrate, order, and persist profiles, subscriptions, routings, and TUN settings. They do not own
network workflows, controller state, test schedulers, or presentation.
- `Storage` owns one application-lifetime backend per collection and exposes live mutable collections for compatibility.
@@ -12,6 +15,8 @@
- Stage fallible decode, migration, or reconciliation before deterministic mutation of the live collection. A
subscription commit changes only that group: matched managed profiles retain stable object/profile identity and local
metadata, removed profiles are marked stale, and indexes/order update atomically.
- Persistence is part of the repository commit contract, not evidence that later host/controller side effects succeeded.
Callers report post-commit failures separately and must not claim the durable mutation rolled back when it did not.
- Moving a profile between subscription displays does not automatically make it remotely managed; preserve the explicit
distinction between local membership and synchronization ownership.
- Verify legacy/current/unknown-field round trips, malformed roots, restore-failure preservation, ordering/stable
+8
View File
@@ -1,5 +1,8 @@
# Service guidance
Inherit the root, package, model, repository, plugin, core, and Qt lifetime rules. This scope owns multi-stage workflows
and temporary resources, never durable collections, shared transition authority, or presentation.
## Workflow ownership
- Services own workflows and temporary resources; controllers own shared state, repositories own durable collections,
@@ -33,6 +36,9 @@
Post-commit reconnect/test invalidation failure is reported without undoing the committed profiles.
- Log transport, traffic collection, and metric history remain bounded and independent of page visibility. Rendering may
be lazy; collection/draining ownership is not.
- Logging accepts concurrent producers through one bounded ordered model; runtime-only clearing and retention cannot
block producers with unbounded synchronous traversal. Metrics sampling owns its worker/future generation and discards
results after disconnect, disablement, replacement, or shutdown.
## Profile testing
@@ -53,3 +59,5 @@
- Cover success plus invalid, stale, superseded, timeout, cancellation, partial acquisition, hidden-page, reentrant, and
repeated-shutdown paths. Assert current identity at write-back and exact cleanup of pools, threads, sockets, replies,
timers, ports, runtimes, callbacks, and host mutations.
- Test pre-commit failure with unchanged live/persisted state separately from post-commit side-effect failure. Never use
a broad rollback assertion to conceal which boundary actually committed.
+6
View File
@@ -1,5 +1,8 @@
# Outer process guidance
Inherit the root and package guides. This scope preserves the exact outer child-process/crash protocol and is not a
general-purpose utility bucket.
- `Utility` owns the child-side wrapper used by the outer application process and crash/exit translation. It is not a
miscellaneous helper namespace and does not own application composition, repositories, runtimes, or UI policy.
- `AppMainProcess` owns one exact Qt application child and one small synchronized crash-log result. Do not add a
@@ -10,6 +13,9 @@
failure never replaces the primary failure.
- The parent entry point joins only the child it created and shows the fallback Qt report only for a nonzero result.
Never discover or terminate processes by name, and keep normal/source/packaged command-line entry points equivalent.
- Crash reporting transports only bounded diagnostic text and a semantic result from the owned child. Failure to render
or save the fallback report must not spawn another supervisor, mutate application state, or replace the original exit
status.
- 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.
+6
View File
@@ -1,5 +1,8 @@
# Reusable widget guidance
Inherit the root, package, and Qt guides. This scope covers reusable controls and model/view adapters below page
composition; it does not own application workflows.
## Presentation and identity
- Widgets present state below pages/windows. Prefer explicit controller/service/repository inputs and do not add new
@@ -22,6 +25,9 @@
- 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.
- Model notifications describe the smallest real source mutation. Never use a reset or full repaint to hide incorrect
proxy/source mapping, stale indexes, or missing stable-identity restoration after insert, delete, move, filter, or
sort.
- Verify sorted/filtered commands, notification ranges, identity-preserving move/delete, real keyboard focus and nested
shortcuts, subscription/test cancellation, hidden-page rendering, exact cell updates, optional WebEngine fallback,
and repeated cleanup to baseline. Update this guide when ownership moves; never move service orchestration back into
+6
View File
@@ -1,5 +1,8 @@
# Window and page guidance
Inherit the root, package, Qt, widget, controller, and service guides. This scope owns persistent page composition and
top-level presentation, not shared domain state.
## Composition and shared state
- `MainWindow` owns the persistent built-in page tree and navigation; plugin pages enter through the plugin navigation
@@ -19,6 +22,9 @@
- Long-lived pages construct persistent controls, models, timers, services, and connections once. Page visibility may
coalesce log/graph painting or deliberately gate a lazy endpoint lookup, but it never owns log collection/draining,
traffic sampling, subscription schedules, or an already-started request.
- A page that creates a service must make its process-lifetime or page-lifetime ownership explicit and expose one
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 windows such as
the text editor and parent-owned settings dialogs retain one explicit owner, reset on reopen, and use normal close
semantics; do not convert every top-level surface to delete-on-close or global retention.
+5
View File
@@ -1,5 +1,8 @@
# Icon source guidance
Inherit repository-wide rules from the root `AGENTS.md`. This top-level scope governs icon source/provenance and the
resource-manifest contract; it does not govern general UI layout.
- Reuse an existing semantic icon before introducing a new asset. SVG sources stay compact vectors without scripts,
remote resources, embedded rasters, editor metadata, or hard-coded page backgrounds.
- Follow the established monochrome/current-color convention so the shared `AppQ*` presentation layer can tint icons.
@@ -7,5 +10,7 @@
- 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 compatible PySide6 resource
compiler. Never hand-edit generated resource code.
- Treat the alias as the application-facing identity and the source path as an implementation detail. Search both before
replacement so an apparently unused file is not removed while still generated or consumed through an alias.
- 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.
+7
View File
@@ -1,5 +1,8 @@
# Furious test guidance
Inherit repository-wide rules from the root `AGENTS.md`. This scope specializes isolation, evidence, resource ownership,
and test-tier selection; test convenience never weakens a production invariant.
## Isolation is a product invariant
- Tests must not affect a running Furious instance, production settings/data, desktop windows, tray, system proxy, DNS,
@@ -10,6 +13,8 @@
cleanup targets only those resources. Normal suites require neither network access nor installed proxy cores.
- Tests may exercise real Qt event loops, subprocesses, and compiled probes when that boundary is the defect, but use a
hermetic child, temporary settings, disabled singleton/tray/restoration, and mocked host mutation.
- Import order is part of isolation: select the offscreen Qt platform and temporary settings identity before importing
modules that can create Qt/application globals. A late patch is not equivalent to preventing the side effect.
## Test the contract
@@ -30,6 +35,8 @@
- Run the narrow module first, then the affected tier documented in `tests/README.md`. The release-confidence tier is
explicitly opt-in with `FURIOUS_VERY_HEAVY_TESTS=1`; packaged/manual smoke work uses disposable environments.
- Benchmarks report scale and latency but are not correctness gates. Keep deterministic scale assertions in normal or
stress tests and avoid machine-dependent elapsed-time thresholds unless the test is explicitly diagnostic.
- Update `tests/README.md` when coverage ownership, modules, commands, tiers, opt-ins, or environment requirements change.
The final unittest status and process exit code are authoritative even when negative paths intentionally log errors.
- Review new tests for production-state mutation, live network dependence, process-name cleanup, unbounded waits, shared