Refine repository guidance and ownership invariants

Signed-off-by: Loren Eteval <loren.eteval@proton.me>
This commit is contained in:
Loren Eteval
2026-09-19 19:42:53 +08:00
parent 4fe6528b41
commit 87597d7ffd
27 changed files with 95 additions and 58 deletions
+6 -3
View File
@@ -10,7 +10,9 @@ exceptions; it does not define the source test suite or imply that every package
dependent WinGet flow. Preserve permission, secret, environment, `if`, and `needs` boundaries.
- `workflows/matrix-build.yml` owns the shared binary matrix, called by `workflows/deploy-pypi.yml` and also run hourly or
manually. Its standalone runs build, verify, and upload artifacts with read-only repository permissions; publication
remains in `workflows/deploy-pypi.yml`.
remains in `workflows/deploy-pypi.yml`. The WinGet publisher's installer selection is another explicit contract:
validate its filename filter against produced artifacts and the intended manifest architectures. Editing an
individual downstream manifest PR does not change future automatic publication.
- Treat each matrix row as a supported product target with explicit runner OS/architecture, Python, Qt/PySide source,
native-binding toolchain, compatibility floor, `Deploy.py` output, and upload pattern. Artifact names and architecture
checks must agree; never infer target architecture from the host label alone.
@@ -30,8 +32,9 @@ exceptions; it does not define the source test suite or imply that every package
newer matrix rows cannot prove that floor. Likewise, successful Qt imports do not prove event-loop or binding-call
compatibility. Default-to-newest dependencies/assets still need recorded provenance and deterministic assertions
at ABI/feature boundaries; pin or checksum external build tools where the workflow establishes that boundary.
- The workflow default shell is Bash, including Windows jobs. Select PowerShell explicitly for native Windows paths,
process APIs, or PowerShell syntax, and keep OS/architecture conditions on the step that owns the difference.
- Inspect shell defaults per workflow/job: matrix and publication workflows set Bash, including Windows jobs;
the source-test workflow uses runner defaults. Select PowerShell explicitly when native Windows paths/process
APIs need it, and keep OS/architecture conditions on the step that owns the difference.
- Flatpak checks run inside the installed sandbox, inspect the application's required native closure rather than every
unused Qt plugin, and fail before upload. Do not mask an actually loadable plugin/runtime mismatch with a broad allowlist.
- Generated helper files, downloaded SDKs/assets, build directories, and local bundles are disposable workflow inputs;
+3 -4
View File
@@ -30,7 +30,6 @@
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
scopes and toolchains; their manifests and local guides govern their code, not Furious's Python/Qt recipes.
Git diff alone cannot verify ignored guides: compare their paths and contents with the initial inventory too.
## Operating model
@@ -130,6 +129,6 @@
likely to become stale, circular references, and wording that freezes incidental structure.
- 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.
Keep run-specific counts, versions, diagnostic experiments, and defect inventories in the work report; guidance
retains the required invariant and a source/test anchor. Do not repeatedly append symptoms to a local guide.
During guidance-only work, report defects separately instead of changing production code to satisfy the prose.
+3 -3
View File
@@ -53,9 +53,9 @@ place.
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.
Compatibility normalization must be narrow, intentional, and tested separately from observational loading.
A dict-like profile exposes its connection document through the mapping interface, not its complete persistence
record. Choose the explicit profile, metadata, or connection representation required by each boundary; generic
mapping conversion is not a profile backup.
Choose the representation required by the next boundary: profile for identity/metadata, connection document for
backend preparation, repository record for persistence. Consult Models/Repository for their copying and encoding
contracts; converting between these representations does not itself validate, isolate, or commit data.
- Import, clipboard, share-link, file, and QR paths reuse the owning plugin codecs and validation. QR is a presentation
transport, not a second protocol parser. Decoding a transport envelope, validating a protocol, and committing a
profile are separate boundaries: a recognized envelope is not permission to clear a group or import an unsupported
+4 -4
View File
@@ -38,10 +38,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.
- 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.
- Capture intended identities/input before yielding. Selection commands retain target IDs and re-resolve live
objects at confirmation; export commands may instead need immutable payload snapshots. Choose that policy at
command start so later selection or edits cannot retarget deferred work. Progress reports actual completed work;
rejecting a progress dialog stops later batches without undoing 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
+3 -2
View File
@@ -17,8 +17,9 @@ boundary between the outer child-process supervisor and the inner application ev
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
owners remain valid; scheduling `deleteLater()` is not evidence that workers or native resources have finished.
native listeners. Keep each successful sub-acquisition reachable by the stage's failure cleanup before beginning
the next fallible constructor; assigning several constructed owners together does not provide this guarantee.
Restore logging configuration as well as closing handlers. Run service shutdown while its owners remain valid; scheduling `deleteLater()` is not evidence that workers or native resources have finished.
Review cooperative pool drains separately from the cleanup stack's ordering guarantees. The application pool's
timed wait logs unfinished work, whereas subscription preparation waits synchronously after its diagnostic timeout.
Neither policy can be inferred from reverse cleanup order or from the name of a shutdown method.
+2 -1
View File
@@ -16,7 +16,8 @@ generic default.
siblings and unrelated branches. URI export represents the codec's supported projection, not a lossless backup
of every document field; exporting must leave the source document unchanged.
- Malformed external input returns controlled validation with backend context. Do not create a plausible but different
profile, and do not log credentials, complete URIs, or documents.
profile, and do not log credentials, complete URIs, or documents. Keep parsing, editor acceptance, and runtime
validation distinct: a tolerant loader preserves a document for correction without promising it can execute.
- Configuration/runtime modules stay importable without constructing Qt editors. Plugin registration remains explicit
enough for compiled discovery. An editor factory returns a fresh projection, not a repository commit: the caller
owns the editable snapshot, acceptance validation, identity resolution, and eventual write-back. Runtime factories
+6 -5
View File
@@ -11,7 +11,8 @@ preserves the intentionally different direct-subprocess scope for user-selected
- 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.
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.
Check timeout validation through `shutdownTimeout()` and the launch boundary; serializability does not prove
a numeric value is usable by process wait APIs.
- 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.
@@ -30,7 +31,7 @@ preserves the intentionally different direct-subprocess scope for user-selected
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.
including non-finite timeout rejection, 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
@@ -43,6 +44,6 @@ preserves the intentionally different direct-subprocess scope for user-selected
after escalation and readers/watchers that outlast their joins. A failed final reap is a cleanup failure to report;
clearing the runtime's process/thread references must not be used as evidence that those resources exited.
Retain an independent reference in failure tests so an empty runtime field cannot make the test pass. Direct-child
exit also does not prove that descendants closed inherited pipes. `Process.py` currently clears references after
unsuccessful waits; this is a cleanup-contract gap. A repair must retain observable outstanding resources and
coordinate failure semantics with `Furious/Service/RuntimeLease.py`, without broad process-name cleanup.
exit also does not prove that descendants closed inherited pipes. Review `Process.py` and
`Furious/Service/RuntimeLease.py` together: incomplete shutdown must preserve observable outstanding resources
and an owner able to finish cleanup, without broad process-name cleanup.
+3 -2
View File
@@ -18,8 +18,9 @@ exists to preserve Hysteria 1's legacy flat schema and lifecycle without importi
- 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
preparation responsiveness review. A prepared runtime advertises its local HTTP readiness endpoint separately
from child liveness.
preparation responsiveness review. The child receives prepared ACL/MMDB inputs; editing an asset or stored
routing preference does not reconfigure an existing execution. A prepared runtime advertises its local HTTP
readiness endpoint separately from child liveness.
- Capability absence is deliberate: this factory supplies neither native TUN nor a statistics provider. Shared UI
must not infer either from Hysteria 2 support. Download preparation replaces the HTTP listener and removes SOCKS
on a copy; test traffic must use its owned endpoint without applying ordinary connection host effects.
+2
View File
@@ -24,6 +24,8 @@ owns Hysteria 2's nested upstream document, native-TUN capability, statistics, a
native TUN. Managed preparation currently resolves server addresses synchronously; asynchronous readiness does not
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.
DNS failure and insufficient Linux privilege are independent preparation failures. Manual exclusions can satisfy
the former route-input requirement but do not grant the latter privilege or prove remote connectivity.
- 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
+3 -1
View File
@@ -27,7 +27,9 @@ owns Xray's full JSON preservation, routing/assets/statistics, and protocol/tran
- Runtime asset updates stage bytes and digest verification before atomic replacement. Failure preserves the prior
usable file. Network reply and checksum worker have separate lifetimes: cancellation/shutdown must suppress late
hash publication as well as abort requests. The plugin capability owns its lazy updater through shutdown.
`Deploy.py --download` has a separate integrity contract; shared filenames do not make the mechanisms equivalent.
The atomic replacement guarantee applies to each asset file, not a multi-file GeoIP/geosite snapshot.
Test sibling failure without assuming another successfully replaced asset rolls back. `Deploy.py --download`
is a separate build-time integrity boundary.
- Routing selection IDs, user routing documents, and translated built-in labels are different contracts. Preserve
custom document content and named-profile identity while composing runtime routing/API statistics. Trace the
selected repository routing document separately from the connection's own routing branch; neither may be mutated
+4 -2
View File
@@ -17,8 +17,10 @@ compatibility paths.
reconnect preference, and rollback after validation, runtime, TUN, System Proxy exceptions, cancellation, or unexpected-exit
failure. Worker/native callbacks cross to the controllers 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.
after invoking them before acquiring a runtime, completing the connection, or applying further host effects.
This includes the initial profile/state/progress notifications, before a start operation exists to cancel.
Verify that a listener which disconnects during `Connecting` prevents subsequent launch admission, not merely
that the final state label is Disconnected. A pre-emission check 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
+3 -3
View File
@@ -20,9 +20,9 @@ connection policy remains outside it.
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.
Keep an independently observable outstanding child/handle when release fails; forgetting it cannot satisfy
this contract. Review `MultiprocessingRuntime._closeProcess()` together with service lease release when changing
failure reporting or retry ownership, and exercise a child that survives both escalation attempts.
- Process-backed runtimes own exit monitoring and interpretation: publish one typed terminal event per execution,
preserving the raw exit and whether stop was requested. `isRunning()` is a passive liveness query and must not
consume or dispatch lifecycle events.
+3 -2
View File
@@ -14,8 +14,9 @@ provenance; it is not an application-data or settings directory.
- Markdown files in this directory are repository metadata, not runtime data. Keep top-level and nested Markdown files
excluded consistently from setuptools package data and Nuitka inclusion while preserving them in the source tree.
- `Deploy.py --download` performs a networked refresh and may rewrite large, time-varying assets. Run it only when that
mutation is explicitly in scope; inspect its actual integrity checks, provenance, exact changed files, and existing
user modifications. A backend's digest-verified runtime updater does not establish this build downloader's guarantees.
mutation is explicitly in scope; inspect integrity checks, provenance, exact changed files, and user modifications.
Validate each downloaded file and the consumer's expected format; successful HTTP transfer is not format validation
or a transaction over the whole asset set. A backend's runtime updater does not establish build-time guarantees.
## Local endpoint map
+4 -3
View File
@@ -13,9 +13,10 @@ is bundled.
post-commit effects belong to the subscription service/repository path.
- 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.
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. Standard plain/Base64 decoding
materializes input before per-item import can be cancelled; linear parsing is not a size or responsiveness bound.
Review decoded size and work limits at this boundary before adding richer formats.
- Worker safety is a property of the whole preparation path. Standard decoders opt in, but the selected protocol
handlers must also opt in after their shared state, caches, and Qt use are audited. Preserve the GUI compatibility
fallback for unclassified capabilities; a safe envelope decoder cannot authorize an unsafe downstream parser.
+4 -3
View File
@@ -28,9 +28,10 @@ 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`; runtime expressions, attributes, calls, conversions, format
specifications, and concatenation helpers inside that argument are not extractable. A static literal containing
- The extractor recognizes direct `_()` and `gettext()` calls with a static first argument. The only supported
dynamic form is an f-string composed solely of bare names resolved from `Furious.Frozenlib.Constants`; aliased or
attribute-call translators, runtime expressions, conversions, format specifications, and concatenation helpers
are not extractable. Runtime translation alone does not establish discoverability. 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.
+3 -2
View File
@@ -25,8 +25,9 @@ boundaries, not a license for unrelated application orchestration to accumulate
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.
- 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.
- Prefer argument vectors over shell strings. Require host helpers to bound individual external calls; workflow callers
also account for the number of calls, retries, privilege interactions, and rollback. A helper timeout and a total
operation deadline answer different questions; build-time commands and GUI-time mutation have different budgets.
- Windows proxy calls, Linux desktop settings/host bridging, and macOS network-service operations are distinct
paths. Application tun2socks host routing differs from backend-native TUN; preserve privilege, DNS restoration,
and managed route cleanup for the selected path. Some helpers block synchronously and need caller-level
+4 -3
View File
@@ -30,9 +30,10 @@ implementations can satisfy without importing application composition or concret
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
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.
from process codes and readiness timeouts. Bounded stop/dispose is a requirement to verify at each implementation,
not a guarantee supplied by the base class. `Disposed` describes terminal API state; prove release using the
implementation's actual resources, without assuming every runtime owns a subprocess. Define how incomplete
cleanup remains observable to its owner and report violations separately from the required contract.
- Verify cheap/import-independent contracts plus representative runtime, storage, editor, application-exit,
encoding, and configuration implementations. Update this guide when a contract intentionally changes, together
with all implementers and compatibility tests. Start with `tests/test_interface.py` and
+3
View File
@@ -18,6 +18,9 @@ never live persistence, Qt presentation, plugin discovery, or workflow execution
never become core 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.
Replacing a connection preserves the logical profile's metadata/ID but may create a new wrapper. Consumers must
choose explicitly between logical identity and exact-object ownership; neither copying nor equal IDs transfers
a live repository or runtime reference automatically.
- 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.
+5 -2
View File
@@ -26,8 +26,11 @@ remains in each implementation.
- Registries own plugin/capability instances and descriptors; created editors and runtimes transfer to their
callers. Capabilities may retain explicitly owned reusable services with shutdown obligations. Do not cache
created transient UI in the registry or treat the registry as the connection/repository authority.
- Once a runtime factory returns a valid launch, the caller acquires that exact runtime even if start raises, so partial
resources can be stopped/disposed. Return no runtime only when none was acquired.
- Separate factory construction, registry result validation, and execution start. A factory owns partial resources
until it returns a valid launch; the caller cannot recover an object hidden by construction failure or an invalid
result shape. After valid transfer the caller owns that exact runtime even if start raises. Keep failure evidence
for all three boundaries when changing factory contracts; returning no runtime after acquisition loses cleanup
authority.
- Plugin/model data is untrusted at the boundary even though installed code is trusted to execute. Validate types,
ownership, required fields, and QObject validity before publishing results.
- API and model layers never import concrete plugins. Bundled backends/extensions obey the public lifecycle; their
+3
View File
@@ -72,6 +72,9 @@ behavior, and lifetime primitives; pages and services consume them without creat
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.
A zero-delay timer yields work but does not establish ordering against an unrelated Qt event. Express required
ordering through an owned continuation or semantic completion signal and test that boundary rather than one
platform's incidental event order.
## Geometry and verification
+2 -1
View File
@@ -5,7 +5,8 @@ contracts. This scope owns restoration, migration, ordering, and persistence; wo
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.
network workflows, controller state, test schedulers, or presentation. A repository method name does not imply
serialization: trace its mutation and `sync()`/cleanup calls to locate the actual persistence boundary.
- `Storage` owns one application-lifetime backend per collection and exposes live mutable collections for compatibility.
Do not add a second cache/snapshot authority. Prefer named repository mutations so validation and commit boundaries
can move behind the repository over time.
+4 -3
View File
@@ -28,9 +28,10 @@ for execution, and Qt for lifetime primitives. This scope owns multi-stage workf
observe the primary runtime, acquire optional tun2socks/DNS resources, and mutate host networking in platform
order before commit. Preserve Windows runtime-before-device, Linux device-before-runtime, and macOS
survival-before-DNS ordering. Failure/cancellation releases attempt-owned runtimes and registered host cleanup.
The synchronous start path is a compatibility boundary, not the default GUI mechanism. Timed readiness/DNS
continuations do not make synchronous platform commands or backend preparation interruptible; audit those calls
and shared route bookkeeping separately.
The synchronous start path remains a compatibility boundary. Review GUI responsiveness at each stage, including
factory preparation, host commands, and reverse cleanup: a scheduled start only defers the first call. Readiness
timers and asynchronous DNS cannot preempt synchronous work. Keep cancellation checks at reentrant stage boundaries
before acquiring the next resource, and audit shared route bookkeeping separately from attempt-local leases.
- Construct a runtime event router before asking a plugin to create its runtime. One lease owns the runtime/router from
acquisition through attempt ownership, commit, and reverse-order release; commit changes logical delivery without
replacing the runtime callback. Worker-thread exits are queued to the router's Qt thread, delivered at most once, and
+3 -1
View File
@@ -13,7 +13,9 @@ protocol and is not a general-purpose utility bucket.
installed only after the factory returns, so pre-construction signals are outside this wrapper's handler coverage.
Preserve semantic exit codes and original exception/traceback context; crash-log failure is secondary.
- 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.
That join follows the GUI session lifetime; it is not a short startup-readiness deadline. Tests must bound their
own waits and reap their exact child if the fixture fails. Never discover or terminate processes by name, and keep
normal/source/packaged command-line entry points equivalent.
- Shared crash status is a synchronized Boolean plus the child's semantic exit result; set the flag only after the
diagnostic file is written successfully. Text may include retained logs plus a traceback, so the Boolean channel
does not bound the crash file's size or sanitize its contents. Keep crash-write failure separate from the primary
+3 -2
View File
@@ -39,8 +39,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. 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
metadata-only test results should update the exact cell. Observers may run synchronously at notification boundaries:
expose consistent source contents, activation, and index/deleted fields before publishing completion. 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
+3 -1
View File
@@ -40,7 +40,9 @@ state.
- Use normal layouts and `AppQ*` controls. Restore top-level geometry only after persistent composition and through the
canonical first-show path; never-shown Qt fallback geometry must not overwrite a prior user decision.
- QR export captures capped independent profile snapshots before deferred work. Incremental generation is owned by
the result window and stops on close; a malformed item cannot retarget or invalidate completed tabs. Resizing
the result window and stops on close; a malformed item cannot retarget or invalidate completed tabs. Attempted
items and successful tabs are separate counts: failures still advance the batch, and an all-failed export closes
its empty window. Cancellation preserves already generated tabs while releasing pending snapshots. Resizing
scales the cached module image at integer factors with its quiet zone, rather than regenerating or smoothing
secret-bearing QR content. Reuse plugin export semantics and never log the encoded URI.
- Search debounce belongs to the persistent page: clear/submit cancels pending work, hide stops it, and show applies
+3 -2
View File
@@ -21,8 +21,9 @@ resource-manifest contract; it does not govern general UI layout.
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
- Verify resource identity as prefix plus alias: the default and white collections intentionally repeat aliases
under different prefixes. Check duplicate full resource paths and missing inputs, then inspect control/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
unused. Keep direct installer/application icons in verification alongside Qt aliases: a successful `pyside6-rcc`
invocation proves resource generation, not deployment-icon inclusion or correct themed rendering.
+6 -3
View File
@@ -15,8 +15,9 @@ and test-tier selection; test convenience never weakens a production invariant.
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.
A temporary QSettings namespace does not reset already-cached `Storage` collections: explicitly isolate and restore
live repository fixtures as well as persisted settings, especially when exercising cleanup or partial startup.
Canonicalize both QSettings file paths and the sandbox root before containment checks, including symlinked
temporary directories; retain an outside-path rejection case so portability does not weaken isolation. A temporary
QSettings namespace does not reset cached `Storage` collections: isolate and restore live repository fixtures too.
## Test the contract
@@ -50,7 +51,9 @@ and test-tier selection; test convenience never weakens a production invariant.
explicitly opt-in with `FURIOUS_VERY_HEAVY_TESTS=1`; packaged/manual smoke work uses disposable environments.
Discovered tests must be self-contained in the checkout: do not load or execute source from Git history.
The standalone log benchmark compares saved JSON timing reports; keep that optional measurement outside
unittest and report opt-ins, platform skips, and standalone measurements separately.
unittest and report opt-ins, platform skips, and standalone measurements separately. Discovery is an inventory,
not execution evidence: record the actual runner result, opt-in state, and skips. Standalone benchmarks and
compiled fixture entrypoints need separate invocations; a full discovered-suite pass does not run them.
- Source-only tests and an offscreen platform do not prove a packaged Qt runtime. Compiler-sensitive changes need
native lifecycle tests and the compiled fixture documented in `tests/README.md`, including accept/reject/close
and owner-first teardown. An unavailable private Nuitka counter is unknown, not measured zero; combine toolchain