Skip to content

Engineering and Verification Rules

星冉 edited this page Jul 22, 2026 · 2 revisions

Engineering and Verification Rules

中文

This page is the unified baseline for code placement, refactoring, collaboration, testing, and performance verification. It serves the current code and does not require compatibility with old versions, data structures, storage paths, or historical behavior.

Non-negotiable invariants

  • scrcpy video, optional audio, and control sockets must be established sequentially; parallel socket establishment is forbidden.
  • Configuration, device-capability cache, and runtime state remain separate; global state must not duplicate session facts.
  • ADB connection candidates may race, but the winning session resources have one owner and deterministic release.
  • Do not add compatibility branches for old versions or historical behavior; migrations target the current model and path.
  • User-visible features provide Chinese and English, diagnostic logs, and recoverable failure behavior together.

See Session Configuration and Connection Lifecycle and ADB Connection Lifecycle for connection details.

Code placement

Location Responsibility
app/ Activity, top-level navigation, and application wiring
feature/<name>/ User features, UI, local state, and feature orchestration
infrastructure/<domain>/ ADB, scrcpy, media, protocol, and system implementations
service/ Foreground services and their direct lifecycle collaborators
core/ Stable shared models, constants, copy, storage, design system, and utilities

Identify the owner and data flow before choosing a directory. Logic used by one feature and still changing does not move into core/ early.

Data flow and abstractions

The preferred direction is UI → ViewModel/feature orchestration → runtime or infrastructure → system/transport.

  • UI does not orchestrate ADB, sockets, or decoders directly.
  • A ViewModel exposes screen state, accepts user intent, and orders calls for its feature.
  • An abstraction must hide complexity, isolate side effects, serve multiple stable callers, carry independent business meaning, or materially improve testing; otherwise keep code local.
  • Avoid UseCase, Repository, Manager, Facade, Wrapper, or Bridge layers that only forward calls.
  • Reduce the number of jumps needed to understand the main path before optimizing file length; code that changes together should stay together where practical.
  • Split large files by real responsibility, not to create symmetric directories full of low-information files.

UI, copy, and logging

  • UI uses project tokens and shared components; see UI Design System.
  • User-visible copy uses TextPair; see Bilingual Text and Copy.
  • New logs use the correct category, tag, and level and never record keys, pairing codes, clipboard bodies, or private file content.
  • Error logs include a stage and stable identity so investigation can follow configuration, ADB, server, sockets, media, and control.

Test layers

  • Unit tests: pure rules, parsers, protocol boundaries, state transitions, selectors, and ViewModels.
  • Integration verification: ADB verify/forward/server, scrcpy socket order, transport recovery, and release during session stop.
  • UI verification: critical Compose states, both themes, both languages, small screens, rotation, and keyboard visibility.
  • Main-path regression: USB, TLS, socket, decoder, control, or lifecycle changes require more than a local function test.

Choose the minimum verification set by risk:

  1. Documentation: links, bilingual pairs, facts, and formatting.
  2. Pure Kotlin rules: relevant unit tests, expanding to :app:testDebugUnitTest when warranted.
  3. Android/Compose or resources: unit tests plus :app:assembleDebug.
  4. Connection/media/control: automated checks plus real-device regression for affected paths.

If a check cannot run, state why in the delivery notes. “The code looks correct” is not a substitute.

Performance reasoning

Classify the issue as transport/socket, decoder/render, UI/interaction, or logging/monitoring before choosing metrics.

  • Do not attribute every stall to buffers or treat FPS as the only performance conclusion.
  • Measure startup, steady state, and shutdown separately, distinguishing spikes from sustained degradation.
  • Compare before and after with the same device, session parameters, and operation path.
  • When changing connection concurrency, inspect resource races, cancellation, winner ownership, and socket order.
  • When changing logging or monitoring, confirm observation does not add material noise or allocation pressure.

Collaboration and review

  • Parallelize only work with clear boundaries and non-overlapping write targets; sequential refactoring on one main path is integrated centrally.
  • Preserve workspace changes outside the task and do not casually expand scope.
  • Review layer ownership, duplicate state, bypass paths, hollow abstractions, useful logs, and risk-based test coverage.
  • Code, tests, bilingual wiki pages, and indexes are one feature change and should finish in the same cycle.
  • Do not add a one-off analysis report in place of a canonical technical page; merge durable conclusions into the owning topic.

Pre-push documentation gate

When a human runs git push in the Screen-Remote/ subrepository, the pre-push hook must first inspect the tip commit message:

  • With the exact confirmation marker: allow the push immediately.
  • Without it: invoke $screen-remote-engineering, read all outgoing committed code, update the outer external/wiki/ as needed, generate a marked commit message, and reject this push attempt.
  • Run the review with gpt-5.6-sol and medium reasoning; keep the app subrepository read-only and make only the outer Wiki workspace writable.
  • While the review is running, store its exact Codex session ID and SHA range under the subrepository Git state directory. After a terminal interruption, run make wiki-resume from the outer root to continue that session, then clear the recovery context after the message is generated successfully.
  • The subrepository pre-commit hook rejects commits while the recovery context is non-empty, preventing history changes before review completion; a missing or empty context does not block commits.
  • The hook must not rebase, amend, commit, or push.

The exact marker and script behavior are defined by the repository hook/skill; the wiki does not duplicate a value that could drift.

Delivery checklist

  • The change preserves all non-negotiable invariants.
  • New code has one clear owner and introduces no bypass state or hollow wrapper.
  • Chinese, English, logs, and error behavior are complete together.
  • Tests, builds, and real-device regression match the risk.
  • Documentation links, indexes, and code facts are synchronized.
  • Other workspace changes remain untouched.

Clone this wiki locally