Next-generation platform engineering handbook

Engineering contracts and risk gates. See delivery status for runnable entry points, individual implementations and actual evidence. This handbook defines team responsibilities and acceptance boundaries; illustrative schemas/APIs do not replace source. OCI preparation, formal offline builds, software candidates and physical qualification are accepted separately.

See next-generation-platform.md for the platform design and integration-contracts.md for external product, Board and component contracts. This handbook turns those boundaries into rules that a team of about ten can execute, review and maintain. Those design documents define the final interfaces and directories.

1. 工程目标与完成的含义

The engineering system must answer four questions: what was selected, whether implementation meets its contract, whether actual resources and timing meet product requirements, and whether the delivered artifact is the one verified. Tool counts, test counts, page counts and green pipeline counts are not goals.

The first version follows these principles:

  • One default configuration input, one resolved result and one software dependency graph. Different tools must not interpret the same selection independently.

  • Standard C, CMake and testing tools each do their own job. Custom tools add only configuration semantics, hardware resource validation and evidence binding.

  • The platform provides shared mechanisms and truthful capabilities. Products own business workers, protocols, partitions, updates, health and manufacturing policy.

  • Compilation, host models, actual kernel execution, ARM linking, physical measurements and release qualification are recorded separately; none substitutes for another.

  • Make failure paths, resource boundaries and concurrency contracts verifiable before optimizing performance. Never trade ownership or settlement conditions for apparent speed.

  • Each stage has executable exit conditions. Plan completion, implementation completion, software acceptance, physical acceptance and release qualification are different states.

The user has deferred physical device operations. The engineering model can first deliver software and HIL tooling preparation; the physical stage remains not executed until a real station and actual results are available.

2. 目录、语言与依赖边界

Recommended production-code organization follows these responsibilities. This table is a directory convention, not another automatic loading or startup framework.

Directory

Engineering responsibility

core/

Small shared types, statuses and foundational contracts, with bounded infrastructure startup; no product main loop.

arch/

CPU-local interrupt state, barriers, necessary atomic primitives and optional timing foundations.

soc/

Exact silicon/variant, clocks, controllers, IRQ/DMA and private vendor SDK integration.

io/

Typed I/O contracts, explicit implementation integration surfaces and necessary portable adapters.

os/

Bounded OS/backend integration; application tasks and scheduling policy belong to products.

components/

Shared components that can be selected, tested and linked independently.

tools/

Configuration parsing, build entry points, artifact checks, evidence and packaging tools.

tests/

Host contracts, fault models, link fixtures, external consumers and HIL tooling tests.

Products and Boards may be external packages. Public examples demonstrate product assembly without becoming mandatory platform business modules. Maintained SoCs and Boards use explicit targets; directory scanning, name matching and implicit default platforms never select implementations.

2.1 Isolating C11 production code from C++ tests

First-version production modules use C11; necessary startup/CPU primitives use controlled assembly. Enabling tests must not add a C++ runtime, exceptions, RTTI or STL dependencies to production targets. Public C headers must be self-contained and provide required C++ linkage declarations so external C++ products can consume the C API.

New behavior tests for host C APIs, components and providers use C++17, GoogleTest and GoogleMock. Helpers, fault injection, host fixtures and mock SDKs belong only to test targets; directory-global includes/defines must not leak into production compilation. Python tools use stdlib unittest and do not require a Python runtime in embedded firmware. Historical C models remain regressions; new behavior follows the TDD contract below.

Verify at least three consumption boundaries: a pure C public-header consumer, a C++ public-header consumer and a real external product consumer. Production target interfaces and resource contracts stay consistent with tests enabled or disabled; instrumentation-profile artifacts are identified separately.

2.2 Public headers must establish a real compile boundary

Separate public, provider and private headers physically. Ordinary consumers receive only selected public include roots; SoC, Board and implementation adapter targets receive the provider/private roots they need. Placing every header in one PUBLIC root and saying “do not include it” does not establish isolation.

Checks include positive and negative cases: public consumers compile necessary types but cannot directly include vendor, private-controller or implementation-registration headers. Visible SDK source does not mean every target should inherit its include paths.

Manage vendor source and rules separately. Public structures must not contain vendor types or require products to inherit vendor compilation macros manually to use public platform APIs.

3. 标准 CMake 是唯一软件依赖图

Components, SoCs, Boards, tests and products express sources, usage requirements and link relationships through ordinary CMake targets. PUBLIC, PRIVATE and INTERFACE distinctions are contractual; do not depend on directory-global includes, links or compile options.

  • List maintained sources and known generated outputs explicitly. The first version does not discover arbitrary components through GLOB_RECURSE.

  • CMake targets are authoritative for software dependencies. Configuration JSON and generators do not maintain a parallel “component A depends on B” graph.

  • Target definitions and necessary semantic checks establish legal component selection. Generators emit selections and configuration facts; CMake propagates dependencies and determines build order.

  • Do not build a custom linker or reimplement CMake target graphs, test discovery or incremental builds.

  • Startup, vectors, static bindings and strong IRQ handlers that must survive linking require explicit retention roots and ELF checks. Global whole-archive or deleting retention roots must not conceal assembly defects. The default architecture does not generate a generic device registry.

  • Propagate CPU/FPU/ABI, optimization and instrumentation options through named configuration targets, rather than appending conflicting flags in different subdirectories.

Component sources, public/private includes and target dependencies stay in their CMake definitions. Optional capability metadata describes implementation facts; it must not redefine software dependencies or claim validation solely from metadata.

Generator output should be small and inspectable: resolved configuration, configuration headers, selected-target identities, static resource bindings and necessary linker layouts. Humans maintain ordinary typed C initialization and data paths. Do not generate business workers, scheduling algorithms, driver state machines or a general execution DSL to save a few initialization lines.

4. 首版配置:assembly.toml 到 resolved.json

4.1 One default input model

Assembly uses product-owned TOML schema 2 in assembly.toml: reference an explicit Board, select its exact SoC part, then select the OS/backend, components, instance resources and budgets. Standard Python tomllib parses it; strict field models also provide editor schemas. The CLI exposes init/list-bindings/check/explain/generate.

assembly.toml contains no arbitrary software dependency declarations, shell commands or code expressions. Strings cannot redefine CPU instruction sets, ABIs, controller functions or arbitrary compile flags. Modes and optimization options come from supported named profiles; toolchain rules produce and record actual flags.

The first version introduces no overlay, inherit, recursive merge or additional configuration language. External products express requirements through complete, explicit assemblies. The same field must not have separate override rules in assembly, Board input, CMake cache and environment variables.

SoC inputs declare exact variants, physical memory, controllers and implemented capabilities. Board inputs declare oscillators, wiring and reviewed resource routes. Product assemblies declare application choices and required capacities. Schemas fix field ownership; conflicts fail rather than letting the last input win.

4.2 Parse once; derived outputs have one source

Configuration constructs frozen ConfigurationIR, ControllerIR, EndpointIR and MemoryBudgetIR values. Constructors consume IR directly; resolved.json retains the same decisions, input identities and resolver version. The same resolution derives:

  • Compile-time constants, separate private instances, read-only faces and typed IDs/getters in nexus_factory.h.

  • Explicit selections for CMake.

  • Board route and resource-conflict check results.

  • Linker/region definitions for product layouts.

  • Configuration digests and resource-budget inputs.

Never edit derived files manually. resolved.json is not user input either: missing or mismatched input identities require regeneration, without fallback to an old generated directory. Failed configuration leaves no partial bundle that can be consumed as success.

The resolver rejects duplicate TOML tables/keys, duplicate JSON fact keys, unknown fields, wrong types, out-of-range values, contradictory choices, missing inputs, unimplemented capabilities, illegal IRQ/DMA/pin routes and overlapping layouts. Declared capabilities cannot override implementation capabilities. String conversion to C/headers/CMake requires explicit encoding and escaping; user data is never executed as a script.

4.3 Separate build roots and caches

Each assembly + toolchain + profile combination uses a separate build root. A CMake cache must not silently switch a root to different silicon, Board, backend or ABI. Entry points verify identity and require a new root or bounded reconfiguration on mismatch.

Caches improve speed without establishing acceptance identity. CI may reuse correctly keyed caches, but formal candidates need at least clean-build evidence. Keys include tool environment, configuration and dependency identity rather than only branch names.

4.4 The role of Kconfig

The first version has no Kconfig frontend. Resource safety, static assembly and CMake builds do not require Kconfig.

If configuration scale later justifies an interactive choice/dependency UI, implement a separate Kconfig frontend targeting the same typed IR contract. Define one authoritative frontend and preserve semantic checks. Kconfig, TOML and CMake cache must not all become sources of truth, and implicit select/default must not bypass unimplemented-capability checks.

5. 外部 package 接入

5.1 Component packages

A component provides an ordinary CMake target, explicit public headers, private implementation and validation scope. Applications link it explicitly. add_subdirectory must not start threads, register product main functions, read devices or change the external environment.

Required hardware enters through typed ports and caller injection. Worker, queue, storage and deadline requirements must be contractual and provided or explicitly approved by products, rather than hidden initialization side effects.

5.2 Board package

A Board package contains exact board/silicon identity, declared inputs, a resource manifest and bounded C/CMake wiring. It owns no product tasks, private protocols, product partitions or manufacturing credentials. The existence of onboard devices and routes does not establish electrical validation.

Declared inputs cover compiled Board sources and files needed for generation. Before integration, check routes, resource conflicts, variant/density, clocks and necessary safe initial states. Hashes prove input identity without isolating arbitrary CMake execution; formal builds still use trusted source and controlled environments.

5.3 Product packages and SDKs

Product repositories provide assemblies, main/workers, business scheduling, protocols, partitions, updates and health policy. They consume platform and components explicitly. Standard platform initialization handles infrastructure without generating applications.

The first version primarily promises a relocatable source SDK. Binary SDKs, stable ABI, support windows and LTS each need separate policy and evidence. Every formal source package must be verified by real C/C++ consumers outside the package in fresh directories; success inside the source tree does not establish relocatability.

Pin external packages to exact versions or source commits/digests. Automatically downloading the newest package by name must not enter formal candidate builds.

6. 工具环境、工具锁与入口

6.1 A small set of tools, each with one responsibility

Responsibility

First-version tool choice

Build and test orchestration

CMake、Ninja、CTest

Production compilation

Locked ARM GCC; Native GCC supplies the matching software-validation environment.

Host C/C++ tests

Locked GoogleTest/GoogleMock; no propagation to production targets.

C/C++ formatting and selected analysis

clang-format and clang-tidy from the same locked version series.

Configuration, evidence and packaging tools

Python; tool tests use stdlib unittest; Ruff provides consistent Python formatting/lint.

Formal build environment

Linux OCI image pinned by digest.

Do not stack multiple formatters, equivalent analyzers or build systems by default. Add a second tool only when its distinct value is demonstrated, with explicit ownership, rules and maintenance cost. Tool checks need actual execution; a configuration file is not evidence of success.

6.2 One formal toolchain lock

One toolchain/environment lock pins ARM/Native compilers, binutils/sysroots, CMake, Ninja, Python, formatters/analyzers, Ruff and the build-image digest. Installers, CI and release tools consume it rather than declaring independent versions.

The lock records exact versions, content digests, legal origins and verification methods. Version strings alone do not identify compiler/sysroot bytes. Host platforms may have explicit development entries, but formal candidates initially use one verified Linux environment, without promising unverified host combinations.

A separate dependencies lock pins source revisions, contents, origins and licenses. Source and tool locks have distinct responsibilities; do not combine compiler installation and component dependencies into another software dependency solver.

6.3 One thin entry point calling native tools directly

tools/dev/dev.py calls real CMake, CTest, style and TDD gates, propagates exit codes and verifies fresh test reports. Presets choose build directories; additional native arguments pass through directly, while the sole resolver interprets assembly.

python tools/dev/dev.py doctor
python tools/dev/dev.py configure --preset native-debug
python tools/dev/dev.py build --preset native-debug
python tools/dev/dev.py test --preset native-debug
python tools/dev/dev.py check --preset native-debug

Local development and CI use the same entry point and underlying commands. CI YAML handles triggers, permissions, matrices and artifact transport without duplicating configuration parsing or checking algorithms. Records retain commands, working directories, non-sensitive environment summaries and exit codes; credentials never enter logs or artifacts.

7. Profile、资源预算与性能门禁

7.1 Debugging, benchmarking and production have different identities

Development profiles provide symbols, diagnostics and appropriate checks; Native sanitizer profiles provide ASan/UBSan; benchmark profiles control measurement fixtures and minimize instrumentation; production profiles fix actual optimization, ABI, diagnostics and resource choices.

Profiles do not inherit each other’s artifact qualification. Production mirrors may retain debug symbols, whose presence alone does not change device contracts. Changes in flags, instrumentation or runtime code require new artifact identities. Instrumented timing is not production-image timing; actual release images still need the required acceptance.

The first version does not presume O3, Os or LTO is always best. Compare O2/Os/O3 and LTO on representative workloads, then choose one or two formal optimization profiles. Profile changes rerun compilation, ABI/static-binding/IRQ, correctness, external-consumer and resource checks. Caller-supplied flags cannot override optimization rules arbitrarily.

Production profiles retain necessary parameter, request-state, dynamic-borrow/revocation, resource and safety checks. Class/owner/lifecycle facts already established for fixed ports during build and control paths need not be rechecked on every GPIO data call. APIs define calling context and single-owner assumptions; debug identity assertions are not C permission isolation. Pure debug diagnostics may be disabled, but NDEBUG must not remove necessary failure handling. Optimizations that change numerical contracts, such as fast-math, are disabled by default.

7.2 Budgets come from products, not library advertising

Product assemblies provide reviewed Flash, static RAM, MSP/PSP, task-stack, heap/pool, buffer and deadline budgets, plus workload assumptions. The platform validates their expression; actual artifacts and field measurements verify satisfaction. Reasonable defaults are not product-approved budgets.

Resource reports distinguish Flash LOAD bytes from layout space, .data/.bss, linker-reserved heap/MSP, task/queue storage, management-domain heaps, runtime high-water marks and minimum margins. ELF file size, section Total including debug, or text+bss alone is not total device cost.

Every enabled instance has an explicit resource cost. Trim unused controllers and legacy storage against the actual BOM before discussing abstraction overhead. Before optimizing hot paths, measure fixed-pool capacity, lookup/critical-section duration, copies and background-worker cost.

7.3 Three classes of performance checks

Check

Execution environment and gate

Static resources

PRs inspect actual ELF/maps, block absolute-budget violations and report changes against a baseline of the same profile.

Controlled benchmarks

Host or dedicated MCU runners record successful work, raw time/cycles, sample distributions, measurement overhead and environment; small timing differences on shared cloud runners are trends only.

Product timing

Dedicated HIL checks deadlines, IRQ response, transfer settlement and resource margins under actual production artifacts, loads and interference.

Benchmarks validate successful work; FULL, fast error returns or discarded messages must not count as successful throughput. Pregenerate inputs and exclude unrelated key formatting, logging and measurement storage from the measured interval. Record means, percentiles, maximum observations and failures/retries/drops; average throughput must not conceal tail latency.

MCU timing records clocks, Flash wait states, FPU settings, IRQ/load modes, counter wrap and instrumentation overhead. CPU-cycle measurements and wire/IRQ end-to-end measurements have different responsibilities. Maximum observed duration is not a strict WCET proof; products declare measurement conditions, analysis scope and reserved margin.

Do not block ordinary feature PRs with unstable microsecond thresholds on shared CI runners. Relative timing gates require calibrated dedicated runners and repeatable baselines before tolerances and false-positive handling are reviewed.

8. 五层验证流水线

8.1 Fast local: find problems early

Run input/schema checks, formatting for changed owned files, incremental compilation and relevant contract tests. Public interfaces and cross-layer state changes require the developer to run applicable integration sets. Local results state their scope and do not directly qualify a release.

Low-impact documentation and formatting changes use appropriate checks; do not create implementation-mirroring tests for each paragraph. Behavior, state, resource or error-semantic changes need observable success and failure-path tests.

8.2 PR: verify shared contracts remain intact

Required checks include owned-production compilation and selected warnings, formatting, selected static rules, key complete Native contracts with ASan/UBSan, public-header isolation, real external consumers and representative ARM linking/resource checks for two SoCs × two backends.

Configuration parsing, public API, ownership, IRQ/DMA, synchronization, linker, toolchain and release-tool changes trigger full cross-layer checks. Selective testing follows explicit dependencies and risk rules, not path-only guesses. Report the selected plan so an empty selection cannot appear passed.

Tests cover failure semantics and invariants: exhausted pools, stale references, busy/retry, partial initialization, timeout/cancel races, cleanup failures and final buffer return. Native fault models prove their model contracts, not real MCU electrical behavior or DMA settlement.

8.3 Nightly: verify breadth and complex paths

Run all maintained Boards/profiles, complete source-SDK consumers, fault/property/fuzz checks and longer software workloads; retain resource trends. Evaluate dependency/tool upgrades, optimization exploration, second compilers and additional hosts here before adding formal support.

Turn repeatable minimum checks for critical nightly regressions into PR checks. Nightly success does not replace unexecuted mandatory PR checks or justify an unlimited matrix without maintainers and capability commitments.

8.4 Hardware: verify real device conditions

HIL admission first validates exact artifact, profile, board/silicon, fixture, station and required instrument identity, then performs real operations. Check IRQ/DMA, electrical behavior, timeout/cancel settlement, extreme loads, stack/pool high-water marks, power loss/recovery and product deadlines.

Empty stations, wrong images/Boards, missing raw data and host-model-only results cannot produce physical passed status. Record instrument/fixture versions, calibration and load conditions; do not generalize one lightly loaded run on one Board to every density, Board and product.

Tool readiness and device operations are separate. Admission tests alone establish HIL tooling ready; while hardware is deferred, physical qualification remains not executed.

8.5 Release: promote the same candidate artifact

Release candidates bind exact source/dependencies/configuration/environment, actual compilation/linking, ELF/BIN/HEX and evidence. Verify source packages, licenses/SBOM, signatures/provenance and required product physical qualification. Release owners review explicit support scope and recovery policy.

After HIL or signing, promote artifacts with the same hashes rather than rebuilding an image with the same name. Code, configuration, dependency or environment changes create new candidates and rerun relevant qualification. Source-SDK acceptance does not automatically establish binary ABI, signatures, product certification or LTS.

9. Provenance、hermetic与reproducible分开验收

9.1 Provenance: traceable input/output relationships

Every release candidate binds one complete input tuple: platform/product source identities, external package/dependency identities, assembly/SoC/Board/layout inputs, resolved configuration, tool environment, profile and generator versions. Every artifact file has a content hash.

The one-to-one relationship means a candidate’s input context identifies that build’s artifacts, not that a Git SHA can produce only one binary. Different profiles or Boards create separate candidate records. Source SHAs do not replace artifact identity. Identical bytes can appear in different contexts; manifests retain each origin.

Execution reports retain actual commands, exits, planned/actually enumerated tests, compile databases, link inputs/outputs, raw logs and hash references. Unsigned hashes detect changes without proving publisher or approver identity; formal attestations and signatures need their own trust policy.

9.2 Hermeticity: read only declared inputs

Formal builds use pinned images and verified dependencies; downloading and preparation are separate from building. Builds have no network and read no arbitrary host directories, developer credentials, undeclared environment settings or system-tool fallbacks. Sources are read-only, outputs separate, and sources must not change during builds.

Record compiler/sysroot bytes and the tool environment they read, not just compiler banners. Pinned tool versions and Git revisions alone do not make a build hermetic; declared Board inputs do not constrain arbitrary CMake access to other directories.

9.3 Reproducibility: identical inputs repeatedly produce identical outputs

Perform two independent clean builds with different absolute paths and cache conditions; compare target ELF/BIN and declared deterministic package contents. Fix SOURCE_DATE_EPOCH and path mapping, control archive order, mtimes and generated text, and prevent current time or machine paths from introducing incidental firmware differences.

Store execution times, logs, signatures and deterministic payload separately. Avoid self-referential manifests and embedding run timestamps in binaries. For randomized signatures/wrapping, define comparison scope; ignoring arbitrary differences does not establish bit-exactness.

Claim reproducibility only after independent rebuild comparison. A pinned container plus hashes, one successful build or a deterministic source archive is insufficient.

10. 证据模型与失败传播

Use one versioned result schema for run identity, planned/executed checks, exit/status, raw-log/artifact references, qualified scope and limitations. Store full compile databases, maps and logs as referenced artifacts, rather than nesting the same large files in every profile.

  • Missing mandatory checks, zero executions, entirely skipped runs, stale results and tool failures never produce passed.

  • Distinguish passed, failed, not executed and unsupported; unsupported is not a validated implementation.

  • Historical results remain useful comparisons after source/configuration/environment changes but do not confer qualification automatically.

  • Explain results and unresolved conditions by risk; “N tests passed” must not conceal unexecuted critical acceptance.

  • Generate summaries from results. Workflow definitions, existing targets, role files and checked plan boxes are not execution evidence.

  • Retain evidence by candidate/run identity with immutable artifact references. Expiring CI artifacts must not be the sole long-term support record.

Diagnostics preserve actual errors and cleanup results rather than repeatedly wrapping them as generic failures. Tool failures retain investigable output and return nonzero; empty JSON or a successful artifact upload does not establish successful checks.

11. 十人的工作与review模型

Codex currently maintains all Arch/SoC/Board, I/O/OS, component, build/evidence and platform-qualification domains. The ten-person configuration describes work domains and capacity without requiring named individuals. Role files validate paths, backup domains and automated gates; they do not invent GitHub accounts.

Assigned maintenance responsibilities, remote branch rules, independent human review, credentials and release authorization are recorded separately. Product decisions and private qualification remain in external product repositories.

11.1 Ordinary and high-risk changes

Ordinary internal changes undergo domain review and automated gates. Public APIs, dependency direction, IRQ/DMA/ownership, persistent formats, security and release-chain changes also need independent agent or consumer cross-layer review and executed failure-path evidence. Agent review is not independent human approval; where remote rules require human review, record its actual state.

Do not convene an architecture committee for every PR. Small ADRs cover real cross-layer decisions: problem, decision, tradeoff, interface and acceptance. Mechanical renames use ordinary PR descriptions. Review contracts, failure paths, concurrency, resources/timing and maintenance cost; tools handle formatting.

Keep changes reviewable: one explainable behavior with its callers/tests/docs. Do not split interface changes into prolonged broken intermediate states. When products cannot migrate atomically, specify a migration window, compatibility-layer owner and removal conditions; compatibility is not a permanent second object system.

11.2 Work items and exit states

Each item records its problem, owner, dependencies, acceptance and risks. Distinguish design accepted, implemented, software accepted, physically accepted and releasable. List external prerequisites separately rather than hiding hardware or responsibility gaps in implemented status.

Engineering assessment focuses on repeatable failures, escaped defects, resource/timing risks and delivery blockers. Lines of code, PR/test counts, aggregate coverage and document counts are not individual/module performance metrics. Coverage locates unverified paths without proving reliability alone.

Actual product and release owners handle releases. HIL reviewers assess real budgets and qualification scope; security/trust owners assess signing and recovery policy. CI executes mechanically provable conditions without replacing human product decisions.

12. 代码风格、注释与静态检查

12.1 Preserve current formatter and naming rules

Preserve the root .clang-format and .editorconfig rather than creating a new style. Lock tool versions in formal environments. The current configuration declares compatibility with clang-format 14 and later; chosen versions must be verified against it, without using upgrades to change style.

Keep 80 columns, four spaces, no tabs, attached K&R braces, type-side pointer alignment (char* ptr), indented switch cases, current include ordering and at most one consecutive blank line. Do not compress control statements or ordinary function bodies into single lines. Long typed interfaces wrap with the formatter rather than expanding to 100 columns. EditorConfig specifies UTF-8, LF, final newlines and per-file indentation.

Follow the contributing guide and coding standards: snake_case for files/functions/ordinary variables; existing module prefixes such as nx_ and osal_ for functions/public symbols; _t suffixes for types; UPPER_CASE for macros/enumerators/constants. File-static variables use s_; global variables use g_ and should be avoided. Private functions and file-local data are static. Prefer functions, const tables and typed structures over macros hiding control flow or cleanup.

Split files by actual state, lifecycle and responsibility. Do not fragment one state machine into many .inc files to shorten files, or collect every interface in a giant umbrella header.

12.2 Preserve Doxygen form and improve contract content

Follow the existing comment standard. C/C++ uses backslash Doxygen tags: \brief, \param[in], \param[out], \param[in,out], \return, \retval, \details and \note. Align descriptions with current templates; do not introduce @brief style.

Public headers describe parameter directions, returns, necessary errors and shared contracts. Sources do not repeat header \param/\return lists; use \brief, \details and \note for implementation, and simplified \brief for static helpers. Structure/enumeration members use /**< ... */; ordinary/trailing comments use /* ... */, with two spaces before trailing comments. Sections use existing /*---...---*/ templates. C/C++ examples follow the same forms.

Headers retain file headers containing \file/\brief/\author; C sources retain complete \version/\date/\copyright headers, adding \details when needed. Preserve fuller existing headers and licenses. Keep fields accurate without inventing authors, versions or dates. Git/release history supplements rather than replaces file headers; functions do not need new handwritten change logs.

CMake and Shell use # comments; Python uses # and triple-quoted docstrings. C/C++ comment forms do not apply to these languages. Third-party sources retain upstream style and licenses.

Public APIs provide the caller’s contract in those existing forms:

Item

Required meaning

context

Task/ISR context, permitted IRQ priority or masking conditions, and single-core/SMP scope.

timing

Blocking behavior, timeout/deadline origin, units, zero/forever meaning and progression responsibility.

ownership

Object ownership, borrow start/end, copied-handle behavior and validity after close.

callback

Execution context, lock state, reentry permission and borrowing before/after callback return.

failure

Return codes, output validity, remaining ownership and retry/recovery behavior.

resources

Fixed capacity, possible allocations, copies, workers and budget requirements.

Put common rules on types or module contracts; functions document necessary differences using existing \details/\note forms. Internal comments explain errata, barriers, races and invariants rather than restating code. Preserve traceable requirements and licenses without inventing requirement IDs. Better contracts retain the current presentation style.

TODOs reference work items with owners and exit conditions. Capability, timing and “thread-safe” claims need specific scope; wording does not replace proof.

12.3 Selected warnings and static rules

Owned production uses Wall/Wextra and reviewed prototype, shadow, conversion and similar rules. Formal gates block new diagnostics in selected rules. Establish stable meaning under C11 and supported toolchains before enabling rules; do not enable every analyzer rule and produce mass ignores.

clang-tidy consumes actual compile commands and generated configuration within owned boundaries. Vendor targets are handled separately; global silencing must not hide owned defects. Suppressions need specific reasons and local scope; no unexplained whole-directory exclusions.

Cppcheck 2.13 does not read -isystem from compile databases. Tools project it to -I per actual translation unit, preserving ordinary-before-system search order; compiler ABI queries still use original arguments. Like clang-tidy, analysis excludes individually only third-party headers under vendors/ or ext/ that are in that translation unit’s actual SYSTEM directories, recording paths, canonical paths and SHA-256. Owned headers, third-party implementation files, non-SYSTEM directories and aliases to owned files stay checked. No global diagnostic suppression or rebaselining. This owned-code boundary does not prove third-party code defect-free.

These rules form an engineering baseline, not MISRA, functional-safety or other certification. Products requiring conformity need exact standards/versions, scope, deviations, tool qualification and independent review; cert-* or analyzer settings alone do not prove compliance.

12.4 Current implementation and historical migration

The previous architecture had inconsistent file headers, comment tags and formatting. This iteration removed old HAL/OSAL, Runtime and business services and unified current Core, I/O, OS, Arch, SoC, components and tests under existing formatting and backslash Doxygen rules. Root .clang-format and .editorconfig are unchanged.

The format directory list covers all maintained C/C++ and .inc files, including measurement workloads. The installer pins pre-commit 4.3.0 and clang-format 14.0.6 and installs real pre-commit/commit-msg hooks. Default commit checks inspect staged snapshots; manual --files/--all-files checks inspect worktrees. CI runs the same whole-file gates; static analysis uses actual compile databases.

The first audit’s 596 files and 337/291 formatting/comment debts are historical traceability only. Both current frozen baseline debt sets are empty. All new source passes whole-file rules, without new or rebased exemptions. Actual gates for the current commit determine acceptance; historical counts cannot be inherited. Archived records and third-party source retain their own identities rather than posing as current owned-code acceptance.

Environment locks, the unified dev entry, source SDK, ELF budgets, offline reproducibility and HIL tooling are implemented; see delivery scope. Formatters handle layout and comment checkers handle mechanical rules; API semantics still need review and behavioral tests. Security diagnostics are reviewed within maintenance scope without global silencing. Software checks do not replace physical timing, product safety or conformity qualification.

13. 错误、所有权与并发API规范

Use a small set of actionable status classes: invalid input/state/context, unsupported, not found, busy, full/empty, timeout/cancelled and I/O/integrity errors. Optional vendor raw flags remain details without leaking vendor types or flattening distinct errors into generic failures.

  • Return statuses do not trigger global logging or global error callbacks automatically; callers choose policy. Concurrent APIs do not use global errno/last-error as authoritative results.

  • ISR diagnostics use bounded, disableable binary records. Suitable tasks handle string formatting and complex storage.

  • Status and ownership are orthogonal. Define cancel acceptance, terminal results and settled buffers separately; TIMEOUT/CANCELLED alone does not prove buffers returned.

  • Rejected create/open or submit admission creates no valid new handle/ticket and no new borrow. Start/error/timeout after ACCEPTED belong to that request’s result and cannot be relabeled as zero-borrow rejection. Query/receive contracts state whether failure leaves outputs untouched or invalid.

  • Failed close preserves existing references and responsibilities. Rollback reports separately retain the original failure, cleanup failure and remaining ownership; a second error must not overwrite the reason.

  • Check all lengths, offsets and resource multiplication before operations. Protocol/persistence encoding does not depend on C structure padding, enum width or host endianness.

  • volatile is not task/ISR synchronization. Explicit Arch contracts govern atomics, barriers and IRQ masks; single-core rules are not SMP safety.

  • Assertions express internal invariants and explicit fail-stop behavior, not recoverable input/resource handling. Production retains necessary boundary checks.

Finite-resource exhaustion returns contractual failure rather than looping until eventual success. Blocking/retries need budgets; callers or explicit component workers own progression. No undocumented hidden threads or timers.

14. 工程批次与退出条件

Batches may accompany vertical platform slices, but actual results close their status. Time and headcount do not replace exit conditions.

Batch

Deliverables and exit conditions

E1 Tools and entry points

A fresh checkout enters the locked environment; one thin entry calls standard build/test tools; local and CI share implementation and one version authority.

E2 Configuration and integration

One assembly/SoC/Board resolution creates the resolved bundle; contradictory/unsupported inputs fail; real external products/Boards integrate; positive and negative public/private/vendor compile-boundary checks pass.

E3 Vertical contracts and code rules

An end-to-end slice handles success, failure, context, ownership and budgets; C11 production/C++ tests are isolated; formatter and selected rules actually execute.

E4 Software pipelines and evidence

PR/nightly risk matrices execute; missing/zero/skipped/stale results are actually rejected; resource overruns are blocked; duplicate old entries are removed; results bind exact inputs and artifacts.

E5 Hermetic builds and HIL preparation

Formal network-disabled builds pass; independent clean rebuilds compare; HIL admission rejects wrong artifacts/profiles/empty stations; physical qualification remains unexecuted until real measurements.

E6 Product release qualification

Actual evidence and reviewers cover physical, safety, recovery and load budgets; sealed candidates pass signature/provenance verification; identical-hash artifacts are promoted; responsibility and support scope are real.

E1–E4 deliver a complete software engineering system. Tool readiness, hermeticity and reproducibility in E5 are accepted separately; actual HIL closes independently. Neither this handbook, a plan nor software pass counts replaces E6.

E1–E6 describe acceptance domains, not another schedule or task authority. The sole implementation ledger is B0–B6 in execution checklist: E1/E2 start in B1; E3 runs through B2–B4 slices; E4/E5 converge in B5; B6 seals only software candidates. E6 completes later when external products and actual hardware evidence are ready.

15. 首个落地切片

First take one exact Board, one OS/backend and one external product from a fresh checkout to a real consumer build, then expand to another backend and SoC. The slice includes small typed I/O, error/cleanup paths, budgets, public/private include boundaries and raw artifact evidence.

Let this slice justify tools, schemas, CMake modules and review rules. Every new combination adds executed validation and maintenance responsibility. Do not build a vast framework first and claim completion through empty fixtures.

16. TDD 与 GoogleTest/GoogleMock 强制开发合同

New production behavior and defect fixes follow RED → GREEN → REFACTOR: write a failing public-contract test first, execute it and verify that required behavior is missing, implement the smallest correct change, then refactor and rerun relevant tests. For new APIs, initial compile failure may establish interface RED; executable behavior tests follow once the interface exists. Retrofitting regressions for existing behavior does not prove historical TDD.

GoogleTest provides assertions, fixtures and boundary cases; GoogleMock replaces only dependency ports such as hardware, time, notification and executors. Tests call actual public Nexus APIs rather than mocking entire providers, factories or owners and proving their own expectations. Prioritize instance isolation, zero-side-effect rejection, resource conflicts, deadlines, post-cancel draining and final publication order. Success and failure together define the contract; do not duplicate implementation details for counts.

dependencies/googletest.lock.json pins exact framework version, commit, archive SHA256 and license. Host tests extract repository-local archives, with no configure-time downloads or network fallback. tests/google/CMakeLists.txt enables C++17 only in the Native test tree. ARM builds, tests-disabled builds and source-SDK consumers receive no C++ runtime or testing-framework dependency.

Unified execution entry:

python scripts/ci/tdd_gate.py --all --preset native-debug
python tools/dev/dev.py test --preset native-debug

The first command tests the report checker, configures/builds nexus_google_contracts, discovers complete cases in each binary and executes unfiltered tests. It removes GoogleTest filter/shard environment settings, deletes old XML and rejects zero cases, unexecuted/skipped/failed/stale reports or discovery-count mismatches. Raw output, GoogleTest XML and summaries are saved under build/<preset>/tdd/. The second command runs the full existing CTest model/tool regressions; their evidence responsibilities differ.

Installed pre-commit hooks run the same GoogleTest gate for production, test, configuration and build behavior changes; prose-only changes need no rebuild. Hooks check unstaged/untracked behavior before and after execution and compare starting/ending git write-tree values. Modifying/restaging source during execution rejects acceptance without a new summary, preventing worktree repairs or concurrent edits from qualifying different committed bytes. CI executes independently of contributor hooks. --no-verify, SKIP, disabled tests and handwritten XML are not valid acceptance.

Behavior-change reviews name failing tests, actual RED commands/reasons, GREEN commands and scenario coverage. Review checks whether tests first define observable contracts. Automation proves execution, report integrity and validation of current source, but cannot mechanically prove every developer’s historical test-first ordering. One green gate is not complete TDD-process compliance.