docs: define coding-agent contribution standards
This commit is contained in:
1 parent
9c1e7cc7bf
commit
98563dcbee
1 file changed
+478
-131
@@ -1,153 +1,500 @@
|
||||
# AGENTS.md
|
||||
|
||||
Guidance for coding agents (and people) working in this repository. Read
|
||||
[README.md](README.md), [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) and
|
||||
[docs/BUILDING.md](docs/BUILDING.md) first. This file adds two things: the
|
||||
rules the project works by, and how to rebuild the inputs that are not in the
|
||||
repository.
|
||||
Mandatory instructions for coding agents and human contributors working in
|
||||
Snapintosh. This is the complete policy, not an addendum to an earlier AGENTS.md.
|
||||
Apply it to all new changes; do not perform unrelated rewrites of legacy code
|
||||
merely to satisfy a newly introduced rule.
|
||||
|
||||
## What this is
|
||||
Correctness, hardware safety, reproducibility, and maintainability take
|
||||
precedence over expedient implementation. An agent must not claim a result it
|
||||
has not verified or cross a hardware/destructive boundary without authorization.
|
||||
|
||||
Snapintosh is an EL2 hypervisor plus a host toolchain. Together they boot
|
||||
macOS 27 (build 26A428) on an ASUS A16 laptop with a Snapdragon X2 Elite. Its
|
||||
companion, [q1n1](https://github.com/Acelogic/q1n1), is a fork of m1n1 that
|
||||
runs as a UEFI app on the A16 and acts as the EL2 proxy. The Mac host drives
|
||||
everything over USB-C NCM (`udp://enN`).
|
||||
## Start Here: Project & Source of Truth
|
||||
|
||||
| Layer | Where |
|
||||
Before changing code, read the relevant sections of [README.md](README.md),
|
||||
[docs/ARCHITECTURE.md](docs/ARCHITECTURE.md), [docs/BUILDING.md](docs/BUILDING.md),
|
||||
and [docs/STATUS.md](docs/STATUS.md). For hardware execution, also read
|
||||
[docs/RUNNING.md](docs/RUNNING.md). Do not rely on status summaries from earlier
|
||||
sessions in place of the current tree.
|
||||
|
||||
Snapintosh targets the ASUS Zenbook A16 (UX3607OA) with the Snapdragon X2
|
||||
Elite X2E-96-100 and macOS 27 build 26A428. The stock J700/T8140 kernel is
|
||||
normally unmodified; Snapintosh mediates its platform contracts. The present
|
||||
workflow still uses q1n1 and a Mac host over USB-C NCM. Standalone execution is
|
||||
a direction, not an already implemented or authorized replacement for this flow.
|
||||
|
||||
| Layer / responsibility | Primary location |
|
||||
| --- | --- |
|
||||
| EL2 monitor: SPTM/TXM emulation, stage-2 and shadow page tables, compat devices | `probes/xnuboot.c`, `compat/`, `shadow/` |
|
||||
| Boot and run orchestration | `tools/cycle.py`, `tools/cycle_lib/` |
|
||||
| GPU kernel driver (IOGPU subclass, AdrenoDisplay IOMFB) | `gpu/adreno-kext/kext/` |
|
||||
| Metal plug-in (`AdrenoMetal.bundle`, hand-written PM4) | `gpu/adreno-kext/plugin/` |
|
||||
| Shader compiler, AIR to Mesa ir3 | `gpu/air2ir3/` |
|
||||
| Wi-Fi (QCC2072), touchpad and keyboard (I2C-HID) | `drivers/` |
|
||||
| Host tests and replays | `tools/test-*`, `tools/replay-*` |
|
||||
| EL2 monitor, SPTM/TXM mediation and platform emulation | `compat/`, `probes/xnuboot.*` |
|
||||
| 16 KiB guest / 4 KiB shadow page-table translation | `shadow/` |
|
||||
| Boot orchestration, safety checks and logs | `tools/cycle.py`, `tools/cycle_lib/` |
|
||||
| IOGPU kext, display and GPU kernel mediation | `gpu/adreno-kext/kext/` |
|
||||
| Metal plug-in and Adreno command encoding | `gpu/adreno-kext/plugin/` |
|
||||
| AIR to Mesa ir3 compiler | `gpu/air2ir3/` |
|
||||
| QCC2072 Wi-Fi and I2C-HID input drivers | `drivers/` |
|
||||
| Host tests, offline replays and diagnostics | `tools/test-*`, `tools/replay-*` |
|
||||
|
||||
## Rules
|
||||
Priority: legal/credential restrictions and hardware safety are absolute;
|
||||
verified ABI and architectural contracts outrank aesthetic preferences. Where
|
||||
another document specifies an exact build or run procedure, follow it unless
|
||||
it conflicts with these safety rules; disclose conflicts rather than guessing.
|
||||
|
||||
1. **Never commit Apple, Qualcomm or ASUS material.** That covers
|
||||
kernelcaches, KDK files, kexts, dyld caches, IPSW/IMG4 parts, firmware,
|
||||
ACPI dumps, disassembly listings, vtable or ABI dumps, the reconstructed
|
||||
`*26A428.h` headers, and shader sets compiled from Apple's shaders.
|
||||
`.gitignore` lists them. Generate them locally (next section) and keep the
|
||||
results under ignored paths such as `build/` and `downloads/`, or in the
|
||||
ignored `include/` targets named below.
|
||||
2. **Never commit personal or machine data:** home paths, host names, user
|
||||
names, IP or MAC addresses, serial numbers, Wi-Fi names or passphrases,
|
||||
SSH key names, device interface names. Use arguments, environment
|
||||
variables, `tools/cycle_lib/pins.json` (ignored; copy
|
||||
`pins.example.json`) or `ROOT`-relative paths.
|
||||
3. **New features are opt-in.** Put each one behind a compile-time define
|
||||
(`ADRENO_*`, `SNAP_*`) and a `tools/cycle.py` flag or boot-arg. With the
|
||||
define off, the build must stay identical: compare the monitor ELF byte for
|
||||
byte, and the kext section by section.
|
||||
4. **Licensing.** New files carry `SPDX-License-Identifier: MIT`. Code derived
|
||||
from other projects keeps its upstream notice and is listed in
|
||||
[THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md).
|
||||
`compat/adreno-ib-tables.h` is GPL-2.0-only: it is generated from q1n1's
|
||||
`tools/adreno_x2_protect.py`. Don't copy GPL code into MIT files. Treat
|
||||
Linux and other drivers as references: cite `file:line`, and
|
||||
re-implement.
|
||||
5. **Hardware safety.** `tools/cycle.py` boots a real laptop and can write
|
||||
its internal NVMe.
|
||||
- Run only one hardware client at a time.
|
||||
- Keep the battery on AC or at 50% or more.
|
||||
- Leave `--thermal-guard` on.
|
||||
- Respect the GPU clock ceiling (`--gpu-dvfs-ceiling`).
|
||||
- Never issue a single `CP_MEMCPY` larger than 1 MiB. One 4 MiB copy hung
|
||||
the GPU.
|
||||
- `cycle.py` refuses a boot if tracked sources change between `--prepare`
|
||||
and `--boot`, so don't edit the tree while a run is prepared.
|
||||
6. **Before hardware, write down the failure modes and test on the host.**
|
||||
- For risky changes, list the failure modes first.
|
||||
- Model the change in a host harness (`tools/test-*.c`/`.py`).
|
||||
- Add mutants the harness must catch.
|
||||
- Hardware runs are scarce, so batch independent fixes into one run.
|
||||
## Non-Negotiable Safety, Provenance & Compatibility
|
||||
|
||||
## Rebuilding what is not distributed
|
||||
1. **Never commit vendor or locally reconstructed private inputs.** This
|
||||
includes Apple, Qualcomm or ASUS kernelcaches, firmware, restore-image parts,
|
||||
KDK files, kexts, dyld caches, ACPI dumps, disassembly/vtable/ABI dumps,
|
||||
reconstructed `*26A428.h` headers, and shader sets compiled from Apple's
|
||||
shaders. Obtain inputs independently and keep them under ignored local
|
||||
locations (for example `build/`, `downloads/`, and the excluded header paths).
|
||||
Preserve `.gitignore` protections. Do not paste protected source material
|
||||
into PRs, tickets, build logs or test fixtures.
|
||||
2. **Never commit secrets or machine-identifying data.** No personal paths,
|
||||
usernames, hostnames, interface names, IP/MAC addresses, serial numbers,
|
||||
network SSIDs/passwords, SSH keys or device identifiers. Use parameterized
|
||||
paths, environment variables, ROOT-relative paths, and local
|
||||
`tools/cycle_lib/pins.json` copied from `pins.example.json`. Sanitize
|
||||
diagnostic excerpts before publication.
|
||||
3. **Preserve opt-in semantics.** New runtime features require a compile-time
|
||||
gate (`ADRENO_*`, `SNAP_*`, or a subsystem-specific flag) and, where
|
||||
applicable, an explicit `tools/cycle.py` option or boot argument. With the
|
||||
gate disabled, the baseline must remain unchanged. Use the project's
|
||||
reproducible baseline procedure: compare monitor ELF bytes and kext sections
|
||||
when deterministic; investigate build-environment differences rather than
|
||||
waiving a meaningful mismatch. Never silently change default behavior.
|
||||
4. **Honor upstream licenses and attribution.** New project-owned source files
|
||||
use `SPDX-License-Identifier: MIT`; derived files retain their original
|
||||
notices and appropriate entries in [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md).
|
||||
`compat/adreno-ib-tables.h` is GPL-2.0-only, generated from q1n1's
|
||||
`tools/adreno_x2_protect.py`; do not mix GPL code into MIT files. For
|
||||
reference implementations in Linux/Mesa and elsewhere, preserve appropriate
|
||||
provenance, distinguish facts from copied expression, and reimplement
|
||||
independently where required by the project's licensing policy.
|
||||
5. **Hardware safety is not optional.** `tools/cycle.py` can write the real
|
||||
internal NVMe. Only one hardware client may run at a time. Use AC power or
|
||||
maintain at least 50% battery, leave `--thermal-guard` enabled, respect
|
||||
`--gpu-dvfs-ceiling`, and never submit a single `CP_MEMCPY` larger than
|
||||
1 MiB (a 4 MiB copy previously hung the GPU). Never change tracked sources
|
||||
between `--prepare` and `--boot`. Require explicit permission for
|
||||
partition-table changes, persistent firmware modifications, or unsafe
|
||||
clock/voltage operations; do not treat user access to the repository as
|
||||
authorization for destructive tests.
|
||||
6. **Host-first validation.** For risky changes, enumerate failure modes,
|
||||
build host-side models/harnesses (`tools/test-*.c` or `.py`), and add
|
||||
deliberately faulty cases the harness must reject. A successful host test
|
||||
does not authorize an unsupervised hardware run. Batch independent
|
||||
validated fixes into one controlled hardware session when practical.
|
||||
7. **Do not discard known-good reference paths casually.** `gpu/agx*` contains
|
||||
retained virtual-AGX reference material. Its presence is an intentional
|
||||
exception to the prohibition on new parallel implementations. Do not
|
||||
delete it simply to satisfy a style mandate; obtain approval and establish
|
||||
a retirement plan if its removal is proposed.
|
||||
|
||||
You need:
|
||||
- a Mac running macOS 26A428, the same build as the guest. The host can then
|
||||
reproduce the guest's userspace and Metal behaviour offline;
|
||||
- Xcode;
|
||||
- the KDK at `/Library/Developer/KDKs/KDK_27.0_26A428.kdk`;
|
||||
- the J700 kernelcache from the restore image
|
||||
(`tools/fetch-ipsw.py`, then `tools/extract-firmware.py ... j700ap`; see
|
||||
BUILDING.md section 1).
|
||||
## 1. Code Architecture & Repository Hygiene
|
||||
|
||||
Everything below runs on the host and never touches hardware.
|
||||
### Compilation Unit Limits
|
||||
- New or substantially expanded C/C++ implementation files must remain below 1,500 physical lines and 50 KiB, excluding generated code.
|
||||
- Prefer refactoring before 1,000 lines when a file contains multiple unrelated responsibilities.
|
||||
- Do not bypass limits by compressing source, hiding implementations in headers, introducing excessive macros, or creating artificial compilation units.
|
||||
- Existing oversized files are technical debt, not justification for unrelated wholesale rewrites. Refactor incrementally while preserving tested behavior.
|
||||
|
||||
| Missing input | Goes to | Produce it with | Check it with |
|
||||
### Cohesive Header Boundaries
|
||||
- Headers must represent stable subsystem interfaces and ownership boundaries.
|
||||
- Do not create one-function or one-feature satellite headers merely to reduce agent context consumption.
|
||||
- Separate public APIs, private implementation details, hardware register definitions, and generated ABI declarations when their responsibilities justify the separation.
|
||||
- Avoid unnecessary cross-subsystem header dependencies and cyclic includes.
|
||||
|
||||
### No Disposable Source Artifacts
|
||||
- Never commit prototype copies, abandoned implementations, backup files, raw analysis scratchpads, or temporary debugging outputs.
|
||||
- Use ignored development directories for experiments.
|
||||
- Git history is the mechanism for preserving superseded implementations.
|
||||
- Keep intentional diagnostic utilities only when they serve a documented, reproducible purpose.
|
||||
|
||||
### No Parallel Implementation Proliferation
|
||||
- Extend or refactor the existing implementation by default.
|
||||
- Do not introduce competing versions of shader lowerers, register maps, page-table managers, or GPU submission paths without an explicit migration plan.
|
||||
- When replacement is justified, define the new implementation's ownership, equivalence tests, cutover criteria, and retirement conditions.
|
||||
- Preserve intentionally retained reference implementations until their removal is approved.
|
||||
|
||||
### Respect Subsystem Ownership
|
||||
- EL2 owns privileged hardware mediation and authoritative translation state.
|
||||
- Kernel drivers own their operating-system contracts, resource validation, and lifecycle.
|
||||
- Userspace components own API translation, command encoding, and application-facing state.
|
||||
- Host tools own deployment, diagnostics, and offline experimentation.
|
||||
- Do not duplicate authoritative state across layers without defining synchronization and recovery semantics.
|
||||
|
||||
## 2. Memory Management, Translation & Synchronization
|
||||
|
||||
### No Global Lock Across Expensive Operations
|
||||
- Do not hold the global monitor spinlock while walking guest page tables, waiting for GPU work, performing blocking I/O, or executing unbounded operations.
|
||||
- Prefer appropriately scoped synchronization, immutable snapshots, or validated read-mostly structures.
|
||||
- Lock-free and RCU-based implementations require explicit lifetime, memory-ordering, and reclamation guarantees.
|
||||
- Establish lock-order rules and test concurrent updates, unmapping, invalidation, and address-space teardown.
|
||||
|
||||
### Architecturally Correct Translation Invalidation
|
||||
- Batch translation invalidations where practical.
|
||||
- Select TLBI operations according to translation stage, VMID, ASID, address range, shareability domain, and supported CPU features.
|
||||
- Do not substitute stage-1 invalidations for stage-2 invalidations.
|
||||
- Apply architecturally required barriers and break-before-make sequences where applicable.
|
||||
- Prefer appropriately scoped invalidations. Whole-VMID invalidation requires a correctness or measured performance justification.
|
||||
|
||||
### Strict Memory Ownership & Lifetime
|
||||
- Every shared buffer, shadow table, DMA mapping, and GPU resource must have defined ownership and retirement conditions.
|
||||
- Never recycle memory while another CPU, hardware queue, or DMA engine can still access it.
|
||||
- Model CPU/GPU cache visibility, mapping changes, fence completion, and device teardown explicitly.
|
||||
- Add targeted tests for stale translations, use-after-free, double-unmapping, and interrupted completion.
|
||||
|
||||
### No Fabricated Hardware or ABI Contracts
|
||||
- Never invent register layouts, interrupt meanings, firmware commands, SPTM/TXM return values, or private Apple ABI signatures.
|
||||
- Distinguish observed behavior from inferred behavior.
|
||||
- Unsupported behavior must fail explicitly rather than return fabricated success.
|
||||
- Preserve exact verified ABI layouts and PAC-sensitive signatures.
|
||||
- Revalidate private interfaces when changing the guest kernel build or target hardware profile.
|
||||
|
||||
## 3. Performance & Real-Time Execution
|
||||
|
||||
### No Blocking Operations in Critical Paths
|
||||
- EL2 trap handlers, timer and interrupt handlers, GPU completion handlers, and presentation paths must not perform blocking console I/O, host RPC, or filesystem operations.
|
||||
- Use bounded, asynchronous diagnostic buffers.
|
||||
- Do not introduce unbounded polling or synchronous waits in latency-sensitive execution paths without demonstrated necessity.
|
||||
|
||||
### Steady-State Allocation Discipline
|
||||
- Avoid heap allocations in steady-state presentation, interrupt, and GPU submission hot paths.
|
||||
- Prefer initialized, bounded command pools, fence pools, and reusable staging arenas.
|
||||
- Any exception must be documented and justified by profiling.
|
||||
- Initialization and exceptional recovery paths may allocate when safe and appropriately bounded.
|
||||
|
||||
### Correct GPU Submission & Completion Semantics
|
||||
- GPU commands must not reference resources that can be destroyed or recycled before retirement.
|
||||
- Do not report command completion before the corresponding hardware work has completed.
|
||||
- Validate command streams, resource ranges, and privileged register access before submission.
|
||||
- Timeouts must follow explicit recovery procedures, not silently mark unfinished work as successful.
|
||||
|
||||
### Performance Regression Discipline
|
||||
- Do not claim an optimization without reproducible before-and-after measurements.
|
||||
- Report median, tail latency, frame pacing, and relevant correctness counters where applicable.
|
||||
- Compare equivalent configurations, workload traces, thermal conditions, and clock ceilings.
|
||||
- An apparent throughput improvement that introduces visual corruption, missed deadlines, data races, or additional hardware instability is not an accepted improvement.
|
||||
- Do not use measurements collected during GPU recovery, latch-up, or incomplete test runs.
|
||||
|
||||
## 4. Hardware Evidence & Documentation
|
||||
|
||||
### Hardware Register Provenance
|
||||
- Identify hardware registers using named blocks and symbolic offsets.
|
||||
- Document the target SoC or device revision and the supporting technical evidence.
|
||||
- Do not scatter unexplained physical addresses or magic register values throughout implementation code.
|
||||
- Physical addresses must be obtained from verified platform mappings rather than assumed universal constants.
|
||||
- Preserve relevant links to public technical documentation or locally reproducible evidence without committing restricted source material.
|
||||
|
||||
### Explain Non-Obvious Invariants
|
||||
- Comments should explain hardware constraints, architectural reasoning, ordering requirements, and known failure modes.
|
||||
- Comment why the code needs a particular implementation, not merely what its syntax does. Favor hardware constraints, invariants, assumptions, ordering and failure modes over narration.
|
||||
- Exceptions: document what a public API guarantees (parameters, units, ownership, errors, threading), and explain unfamiliar algorithms when the implementation is not self-evident.
|
||||
- Do not write comments that merely restate an if, assignment, function name, or assertion. Never use unexplained agent session tags such as `/* F4: ... */`.
|
||||
- Use static assertions to verify sizes, offsets and alignments, but do not substitute long runs of assertions for an explanation of the hardware requirement.
|
||||
- Explain why a workaround exists, which revisions it applies to, and the observable condition for safely removing it.
|
||||
- Keep comments synchronized with behavior when code changes; delete stale speculation and do not present guesses as verified facts.
|
||||
|
||||
### Evidence Classification
|
||||
- Distinguish VERIFIED, OBSERVED, INFERRED, EXPERIMENTAL, and UNIMPLEMENTED behavior.
|
||||
- A successful compilation does not prove ABI correctness.
|
||||
- A successful offline replay does not prove equivalent behavior on hardware.
|
||||
- Reaching a boot milestone does not prove stability.
|
||||
- Never upgrade a feature's reported status without the corresponding test evidence.
|
||||
|
||||
## 5. Testing & Agent Execution Discipline
|
||||
|
||||
### No Untested Behavioral Refactors
|
||||
- Establish a reproducible baseline before altering functioning monitor, driver, or compiler code.
|
||||
- Preserve existing tests and add regressions for changed behavior.
|
||||
- Verify functional equivalence before attributing performance gains to a refactor.
|
||||
- Report tests as PASS, FAIL, SKIP, or NOT RUN. Never describe skipped tests as successful.
|
||||
|
||||
### Bounded, Reviewable Changes
|
||||
- Keep each change focused on a defined engineering objective.
|
||||
- Do not combine unrelated refactors, new features, and performance experiments without explicit justification.
|
||||
- Do not silently change defaults or weaken assertions to make a test pass.
|
||||
- Never bypass failing tests by deleting them, relaxing expected outputs, or substituting fabricated results.
|
||||
|
||||
### Standalone-First Runtime Design
|
||||
- New runtime drivers and EL2 services must not depend on a connected host for their fundamental operation unless explicitly approved as transitional.
|
||||
- Python host tools remain appropriate for provisioning, diagnostics, offline regression testing, and current experimental boot workflows.
|
||||
- Isolate host transport behind interfaces that can eventually support native on-device operation.
|
||||
- Do not introduce new production-critical RPC dependencies without documenting their removal path.
|
||||
|
||||
### Accurate Milestone Reporting
|
||||
- Every substantive hardware milestone must identify the tested revision, build identity, enabled flags, execution environment, and supporting log or report.
|
||||
- Distinguish partial functionality from end-to-end operational readiness.
|
||||
- Record known limitations and remaining failure modes.
|
||||
- Never claim hardware validation when only simulated, compiled, or host-replayed evidence exists.
|
||||
|
||||
### Preserve Recoverability
|
||||
- Hardware experiments must retain a documented stop, quiesce, and recovery path.
|
||||
- Treat storage partition modifications, persistent firmware writes, and clock or voltage changes outside established safety limits as destructive operations requiring explicit authorization.
|
||||
- Never disable established thermal, power, or storage safety guards merely to complete an experiment.
|
||||
|
||||
## 6. Commit Naming & Git Discipline
|
||||
|
||||
Use `module: imperative change` for every new commit title. This is a
|
||||
repository-scoped prefix convention, not Conventional Commits with `feat(...)`
|
||||
or an invitation to put the issue number in place of a subsystem.
|
||||
|
||||
```
|
||||
<module>: <imperative, specific change>
|
||||
```
|
||||
|
||||
- **Module Identifier:** Use a lowercase, hyphenated module identifier. Prefer the smallest stable
|
||||
owning subsystem: `shadow`, `compat`, `sptm`, `txm`, `gpu`, `adreno-kext`,
|
||||
`adreno-metal`, `air2ir3`, `display`, `wifi`, `input`, `nvme`, `probes`,
|
||||
`tools`, `cycle`, `build`, `tests`, `docs`, or `repo`. Introduce new scopes
|
||||
only for genuine long-lived modules, not individual files or sessions.
|
||||
- **Imperative Verb:** Start the description with an imperative verb (`fix`, `batch`, `validate`,
|
||||
`remove`, `refactor`, `document`, `guard`, `rework`, `add`). Be specific about
|
||||
the behavior changed. Use sentence case only for proper nouns/symbols; do
|
||||
not end the subject with a period.
|
||||
- **Subject Length:** Aim for 50 characters; the hard subject-line limit is 72 characters.
|
||||
When needed, add a blank line followed by a body explaining motivation,
|
||||
tradeoffs, implementation constraints, and test evidence. Wrap body lines at
|
||||
approximately 72 characters, except links and literal commands.
|
||||
- **Single Conceptual Change:** Keep one conceptual change per commit. Do not bury unrelated refactors,
|
||||
generated files, benchmarks or policy edits inside a behavior change.
|
||||
- **No Vague Titles:** Do not use `WIP`, `misc`, `cleanup stuff`, `fix bugs`, vague session labels,
|
||||
agent names, or promotional claims as final commit titles.
|
||||
- **Authorization for Operations:** Do not amend, rebase, force-push, reset another contributor's work, or create
|
||||
commits unless the task authorizes that Git operation. Never claim a commit
|
||||
exists without confirming it.
|
||||
- **Breaking Changes:** For incompatible interface changes, describe migration and compatibility
|
||||
implications in the commit body and PR. Do not casually reassign a public
|
||||
ABI, register layout, or feature flag under the guise of cleanup.
|
||||
|
||||
```
|
||||
Good:
|
||||
shadow: batch stage-2 TLB invalidations
|
||||
compat: release the monitor lock before GPU waits
|
||||
air2ir3: reject unsupported AIR texture operands
|
||||
display: document present-fence ownership
|
||||
wifi: validate QCC2072 ring descriptors
|
||||
docs: define coding-agent contribution standards
|
||||
|
||||
Bad:
|
||||
fixes
|
||||
WIP changes
|
||||
feat(shadow): improve things
|
||||
AI: finished the hypervisor
|
||||
update code
|
||||
```
|
||||
|
||||
## 7. Comments, Documentation & Naming
|
||||
|
||||
The governing principle is **explain the why, not narrate the what**.
|
||||
|
||||
- Comments are warranted for unexpected ordering, architecture-specific
|
||||
constraints, non-obvious invariants, workarounds, concurrency ownership,
|
||||
error cases, hardware errata, and empirically observed failure modes.
|
||||
- Public APIs still require clear *what* contracts: units, parameters,
|
||||
ownership, buffer lifetime, valid threading context, return values and
|
||||
failure semantics. Short algorithm summaries are appropriate for complex
|
||||
transforms or translation logic.
|
||||
- Do not write `// Increment index` above `++i`, duplicate a function's name
|
||||
in prose, or use comments as a substitute for clear naming.
|
||||
- Keep function and variable names descriptive of their actual responsibilities.
|
||||
Avoid session-generated prefixes, meaningless abbreviations and unexplained
|
||||
one-letter identifiers outside narrow mathematical contexts.
|
||||
- Any hardware constant that could be revision-dependent needs a meaningful
|
||||
symbol and a source trail (register block, offset, SoC revision, and
|
||||
independently verifiable evidence). Do not publish confidential register
|
||||
dumps, extracted vendor blobs, or proprietary disassemblies as evidence.
|
||||
- Use `_Static_assert` / `static_assert` for enforceable invariants. Explain
|
||||
why a layout is necessary nearby, especially for guest-visible structs,
|
||||
DMA descriptors, PAC-sensitive vtables, cache-line assumptions, and page
|
||||
sizes. Avoid using hundreds of assertions as replacement prose.
|
||||
- `TODO` / `FIXME` comments must describe the missing behavior, observable
|
||||
failure or acceptance condition, and preferably a tracking issue. Do not
|
||||
leave vague `TODO: fix later`, session TODOs, or speculative claims of
|
||||
completeness. Remove obsolete TODOs when implementing the fix.
|
||||
- Document feature flags, configuration defaults and behavioral changes in
|
||||
the relevant README or reference docs. Keep existing link targets and
|
||||
anchors functional; if a heading must move, update inbound links together.
|
||||
- Avoid stale or overconfident comments: `OBSERVED` and `INFERRED` are not
|
||||
interchangeable with `VERIFIED`.
|
||||
|
||||
### Example
|
||||
|
||||
```c
|
||||
// Good:
|
||||
// The GPU may still read this IB after the submit call returns.
|
||||
// Retire it only after the hardware completion fence is observed.
|
||||
retire_ib_after_fence(ib, fence);
|
||||
```
|
||||
|
||||
### Not
|
||||
|
||||
```c
|
||||
// Bad:
|
||||
// Retire IB after fence.
|
||||
retire_ib_after_fence(ib, fence);
|
||||
```
|
||||
|
||||
## 8. Agent Workflow, Scope & Failure Behavior
|
||||
|
||||
1. **Establish context before editing.** Identify the owning subsystem,
|
||||
existing implementation, relevant tests, feature flags, known failure
|
||||
modes and hardware-sensitive operations. Inspect before replacing.
|
||||
2. **Define acceptance criteria.** State the observable behavior that must
|
||||
change, what must remain identical, and what would falsify success.
|
||||
For multi-layer fixes, document call boundaries and ownership before
|
||||
modifying both sides.
|
||||
3. **Prefer the smallest correct change.** Do not create a replacement driver,
|
||||
header tree, compiler pass or RPC service just because modifying the
|
||||
existing code is more difficult. Respect existing deliberate references.
|
||||
4. **Make errors explicit.** Fail closed on unrecognized monitor calls,
|
||||
unsupported firmware operations, malformed command streams, invalid
|
||||
mappings and ABI mismatches. Never fabricate a successful return value to
|
||||
bypass a failure. Capture enough context to diagnose the rejection without
|
||||
leaking secrets or causing hot-path latency.
|
||||
5. **Preserve behavioral defaults.** Keep changes opt-in where required,
|
||||
account for cleanup/recovery paths, and test failure cases as well as the
|
||||
expected path. Never mute assertions or delete failing tests to create
|
||||
artificial success.
|
||||
6. **Validate at the correct level.** Distinguish syntax/build checks,
|
||||
sanitizer tests, offline reference replays, ABI validation, and hardware
|
||||
validation. Report each separately: `PASS`, `FAIL`, `SKIP`, or
|
||||
`NOT RUN`, with a reproducible command and reason for non-execution.
|
||||
7. **Do not invent artifacts or results.** Never fabricate compiler output,
|
||||
hashes, register traces, performance figures, logs, hardware status,
|
||||
screenshots or benchmark improvements. Do not claim testing on the A16
|
||||
when work was confined to a host or a mock environment.
|
||||
8. **Close with a factual handoff.** Summarize changed files and rationale,
|
||||
tests executed and exact outcomes, known risks, and whether hardware
|
||||
qualification is still required. Do not imply completion if a prerequisite
|
||||
or regression remains unresolved.
|
||||
|
||||
### Change Acceptance Matrix
|
||||
|
||||
| Change category | Minimum acceptable evidence before requesting hardware time |
|
||||
| --- | --- |
|
||||
| Documentation / comments only | Links, anchors, examples and factual references reviewed |
|
||||
| C/C++ refactor | Build or syntax validation, relevant host tests, equivalence checks |
|
||||
| Shadow MMU, SPTM/TXM, TLBI | Translation models, invalidation/ordering cases, concurrency teardown cases |
|
||||
| arm64e kext ABI, IOKit | KDK/kernelcache slot/signature verification and relevant stub checks |
|
||||
| GPU commands, buffers or fences | Host replay, bounds/ownership checks, fault and timeout cases |
|
||||
| AIR to ir3 lowering | IR tests, negative/unsupported opcode cases, pinned reference comparisons when available |
|
||||
| Boot, storage, DVFS or firmware | Offline refusal-path tests and explicit, supervised hardware test plan |
|
||||
|
||||
This matrix describes minimum preparatory evidence, not blanket permission
|
||||
for running privileged tools. Private inputs and dedicated hardware may not
|
||||
be available to a contributor; mark the corresponding checks `NOT RUN` or
|
||||
`SKIP` accurately and explain what remains unverified.
|
||||
|
||||
## 9. Pull Request Standards
|
||||
|
||||
Every PR should contain:
|
||||
|
||||
- **Purpose:** The concrete defect, feature or engineering problem and why it
|
||||
matters; refer to related issues when relevant.
|
||||
- **Scope:** Subsystem(s), files and behavior affected; list what intentionally
|
||||
remains out of scope.
|
||||
- **Design:** Architectural decisions, ABI or register assumptions, locks and
|
||||
lifetime rules, any new feature flags, fallback and recovery behavior.
|
||||
- **Evidence:** Exact commands and PASS/FAIL/SKIP/NOT RUN outcomes; for
|
||||
performance PRs include reproducible before/after data and tail latencies,
|
||||
not just the best average FPS.
|
||||
- **Safety and compatibility:** Changes to destructive operations, hardware
|
||||
ceilings, boot flow, license/provenance inputs, external dependencies,
|
||||
default-off equivalence or guest build assumptions.
|
||||
- **Remaining limitations:** Failures, unresolved questions and required
|
||||
supervised hardware qualification.
|
||||
|
||||
One PR should address one coherent goal. Avoid formatting-only churn mixed
|
||||
with functional changes. For policy-only PRs, no hardware run is necessary;
|
||||
review Markdown links, preserved instructions and changed diff instead.
|
||||
|
||||
## Rebuilding What Is Not Distributed
|
||||
|
||||
Use [docs/BUILDING.md](docs/BUILDING.md) for the overall build. The following
|
||||
inputs must be generated **locally from material the contributor is authorized
|
||||
to use**, and must never be committed. A Mac with the matching macOS
|
||||
27/26A428 userspace, Xcode, the KDK at
|
||||
`/Library/Developer/KDKs/KDK_27.0_26A428.kdk`, and the J700 restore-image
|
||||
kernelcache is required for the relevant workflows.
|
||||
|
||||
| Missing input | Local destination | Produce / recover it with | Verify with |
|
||||
| --- | --- | --- | --- |
|
||||
| `IOMobileGraphicsFamily26A428.h` | `gpu/adreno-kext/kext/include/` | `python3 tools/gen-iomfb-header.py --kc downloads/extracted/j700ap/<kernelcache>` (`--kdk` overrides the KDK path) | `python3 tools/check-iomfb-vtable.py` |
|
||||
| `IOGPUFamily26A428.h` | `gpu/adreno-kext/kext/include/` | no generator yet: follow the recipe below | a stub subclass vtable compare, as `check-iomfb-vtable.py` does |
|
||||
| `IO80211Controller26A428.h`, `IO80211Interface26A428.h`, `IO80211WorkQueue26A428.h`, `IOSkywalkLifecycle26A428.h` | `drivers/snap-qcc2072/include/` | `python3 drivers/snap-qcc2072/re/recover-controller-abi.py --output build/controller-abi.json` for the exact slots and PAC fixups, plus the `re/interface-abi/` scripts (run them from that directory; they import `evidence_guard.py`), then write the header from that evidence with the recipe below | `python3 drivers/snap-qcc2072/re/verify-controller-abi.py --binary <linked kext binary> --report build/verify.json` |
|
||||
| Disassembly of Apple routines (for study only) | `build/` | `python3 tools/kc-disas.py <kernelcache> <address> --until-ret`; find addresses with `tools/kc-xref.py` / `tools/kc-symbolicate.py` | n/a |
|
||||
| air2ir3 pinned shader sets (`render-shaders.pinned.json`, `p7-shaders*.json`) | `gpu/air2ir3/tools/a16ref/`, `gpu/air2ir3/tools/p7ref/` | `AIR2IR3_TREE=<this tree> OUT=build/p7 zsh gpu/air2ir3/tools/p7ref/make-p7-shaders.sh`; q1n1's `tools/a16gpu-render/make-render-shaders.sh` for the render set. Both compile Apple's own SkyLight/QuartzCore shaders from the host. | `gpu/air2ir3/tools/p7check.py`, `a16check.py`. Tests print SKIP when the sets are absent. |
|
||||
| `probes.air` | `gpu/air2ir3/tools/a16ref/` | `gpu/air2ir3/tools/a16ref/build-probes-air.sh` | n/a |
|
||||
| Machine pins | `tools/cycle_lib/pins.json` | copy `pins.example.json`, then set `device` and the q1n1 stage hashes | `tools/cycle.py ... --prepare` |
|
||||
| Mesa | `gpu/air2ir3/third_party/mesa` | `gpu/air2ir3/tools/mesa-setup.sh` (pinned revision) | the air2ir3 tests |
|
||||
| `IOMobileGraphicsFamily26A428.h` | `gpu/adreno-kext/kext/include/` | `python3 tools/gen-iomfb-header.py --kc downloads/extracted/j700ap/<kernelcache>; optionally --kdk` | `python3 tools/check-iomfb-vtable.py` |
|
||||
| `IOGPUFamily26A428.h` | `gpu/adreno-kext/kext/include/` | ABI reconstruction recipe below | Stub subclass vtable comparison |
|
||||
| `IO80211Controller26A428.h`, `IO80211Interface26A428.h`, `IO80211WorkQueue26A428.h`, `IOSkywalkLifecycle26A428.h` | `drivers/snap-qcc2072/include/` | `python3 drivers/snap-qcc2072/re/recover-controller-abi.py --output build/controller-abi.json`, the `re/interface-abi/` scripts, then recipe below | `python3 drivers/snap-qcc2072/re/verify-controller-abi.py --binary <linked-kext> --report build/verify.json` |
|
||||
| Study-only disassembly | `build/` | `tools/kc-disas.py`, `tools/kc-xref.py`, `tools/kc-symbolicate.py` on locally obtained inputs | Do not commit output |
|
||||
| `render-shaders.pinned.json`, `p7-shaders*.json` | `gpu/air2ir3/tools/a16ref/`, `gpu/air2ir3/tools/p7ref/` | `AIR2IR3_TREE=<repo> OUT=build/p7 zsh gpu/air2ir3/tools/p7ref/make-p7-shaders.sh`; q1n1's `tools/a16gpu-render/make-render-shaders.sh` | `gpu/air2ir3/tools/p7check.py`, `a16check.py`; absent inputs mean SKIP |
|
||||
| `probes.air` | `gpu/air2ir3/tools/a16ref/` | `gpu/air2ir3/tools/a16ref/build-probes-air.sh` | Local generator/build validation |
|
||||
| Machine pins | `tools/cycle_lib/pins.json` | Copy `tools/cycle_lib/pins.example.json` and configure locally | `tools/cycle.py ... --prepare` |
|
||||
| Mesa | `gpu/air2ir3/third_party/mesa` | `gpu/air2ir3/tools/mesa-setup.sh` at pinned revision | air2ir3 tests |
|
||||
|
||||
### Recipe: a header for a private Apple C++ class (arm64e)
|
||||
|
||||
Use this for `IOGPUFamily26A428.h`, the IO80211/Skywalk headers, or any future
|
||||
26A428 class. `tools/gen-iomfb-header.py` automates exactly this for IOMFB. If
|
||||
you generalise it, that's the best contribution here.
|
||||
**Do not remove or rename this heading without updating the existing links in
|
||||
[docs/BUILDING.md](docs/BUILDING.md).** The recipe applies to `IOGPUFamily26A428.h`, the
|
||||
IO80211/Skywalk headers, and comparable future private classes. It is about
|
||||
rebuilding interfaces from the contributor's own licensed inputs, not
|
||||
redistributing extracted or reconstructed Apple materials.
|
||||
|
||||
1. **List what the code needs.** For example, run
|
||||
`grep -rhoE 'IOGPU[A-Za-z]+' gpu/adreno-kext/kext/src | sort -u`. Declare
|
||||
only those classes, the methods we call or override, and the fields we
|
||||
touch.
|
||||
2. **Read the vtables from the KDK**, e.g.
|
||||
`.../KDK_27.0_26A428.kdk/System/Library/Extensions/IOGPUFamily.kext/Contents/MacOS/IOGPUFamily`.
|
||||
- Take the arm64e slice with `lipo -thin arm64e`.
|
||||
- The vtable symbols are `__ZTV<len><Class>`.
|
||||
`nm -arch arm64e -m` with `c++filt` names the exported methods.
|
||||
- `dyld_info -fixups` shows each slot's target and its PAC diversity.
|
||||
3. **Declare every virtual in the class that introduces its slot**, in slot
|
||||
order, with parameter types exact enough that the mangled name matches.
|
||||
- On arm64e, a slot's PAC discriminator is derived from the mangled name of
|
||||
the declaration that introduces it. A wrong signature therefore fails
|
||||
pointer authentication and panics at kext load or on first call; it does
|
||||
not just misbehave.
|
||||
- Return types are not mangled. Infer them from callers or overriders, and
|
||||
mark the inferred ones (the IOMFB header uses `ret=` notes).
|
||||
4. **Get the class sizes and offsets.**
|
||||
- `OSMetaClass` is constructed with each class's size, so read it from the
|
||||
metaclass constructor in the KDK binary.
|
||||
- Take field offsets only from code that uses them, and prefer accessor
|
||||
methods.
|
||||
5. **Check against the J700 kernelcache, not just the KDK.** The device
|
||||
kernelcache is what runs. Use `tools/kc-xref.py` and `kc-symbolicate.py` to
|
||||
locate the same vtables there, and confirm slot count, targets and PAC
|
||||
diversities.
|
||||
6. **Prove it.**
|
||||
- Compile a stub subclass with the flags from
|
||||
`gpu/adreno-kext/kext/build.sh`.
|
||||
- Compare its vtable slot by slot with the KDK and the kernelcache, as
|
||||
`tools/check-iomfb-vtable.py` does.
|
||||
- Only then build the real kext.
|
||||
1. **List the required declarations.** Inspect usage in the local source,
|
||||
for example `grep -rhoE 'IOGPU[A-Za-z]+' gpu/adreno-kext/kext/src | sort -u`.
|
||||
Declare only the classes, methods/overrides and fields actually needed.
|
||||
2. **Examine locally available arm64e vtables.** From the contributor's KDK,
|
||||
use `lipo -thin arm64e`, `nm -arch arm64e -m` (with `c++filt`) and
|
||||
`dyld_info -fixups` to identify vtable slots, targets and PAC diversity.
|
||||
The Itanium-style symbol form for a vtable is `__ZTV<len><Class>`.
|
||||
3. **Reconstruct each declaration in the class introducing the slot.** Keep
|
||||
virtuals in slot order. PAC discrimination may depend on the declaration's
|
||||
mangled name: an incorrect signature can panic at load or first call,
|
||||
rather than merely misbehave. Return types are not generally encoded by
|
||||
ordinary C++ function name mangling; infer cautiously from callers and
|
||||
overriders and label those inferences.
|
||||
4. **Verify sizes and member offsets.** Obtain class size from `OSMetaClass`
|
||||
construction and offsets from actual uses, preferring accessors instead of
|
||||
guessing layout or publishing extracted artifacts.
|
||||
5. **Cross-check against the J700 kernelcache.** KDK agreement alone is
|
||||
insufficient: validate slot count, targets and PAC diversities against the
|
||||
actual kernelcache using local `tools/kc-xref.py` and
|
||||
`tools/kc-symbolicate.py` when applicable.
|
||||
6. **Prove the ABI before loading a real kext.** Build a stub subclass with
|
||||
the same flags as `gpu/adreno-kext/kext/build.sh`, compare slots against
|
||||
local KDK/kernelcache evidence (as `tools/check-iomfb-vtable.py` does),
|
||||
and only then proceed to the real kext. Do not commit the reconstructed
|
||||
header or private source evidence.
|
||||
|
||||
## Day-to-day commands
|
||||
## Day-to-Day Build, Test & Debugging Notes
|
||||
|
||||
The full sequence is in [docs/BUILDING.md](docs/BUILDING.md); running on the
|
||||
laptop is in [docs/RUNNING.md](docs/RUNNING.md).
|
||||
The authoritative full sequences are in [docs/BUILDING.md](docs/BUILDING.md)
|
||||
and [docs/RUNNING.md](docs/RUNNING.md). Commands below are examples, not an
|
||||
invitation to operate on hardware without permission.
|
||||
|
||||
- Host tests: `python3 tools/test-<name>.py`. The C tests are built by their
|
||||
matching `.py` driver.
|
||||
- Kext: `gpu/adreno-kext/kext/build.sh`. AuxKC link: `tools/build-auxkc-user.py`,
|
||||
then `tools/auxkc-autoload.py`.
|
||||
- A run: `python3 tools/cycle.py installed-fresh --prefix <name> ... --prepare`,
|
||||
then the same arguments with `--boot --generation 1 --qualification-sha256 <sha>`.
|
||||
After a run: `--quiesce`.
|
||||
- **Host suite:** `python3 tools/test-<name>.py` or the matching C test's documented
|
||||
sanitizer build. Test drivers may compile their native C suites.
|
||||
- **Kext:** `gpu/adreno-kext/kext/build.sh`; AuxKC link helpers include
|
||||
`tools/build-auxkc-user.py` and `tools/auxkc-autoload.py`.
|
||||
- **Controlled boot workflow:** `python3 tools/cycle.py installed-fresh --prefix <name> ... --prepare; validate with --check`;
|
||||
boot with matching arguments, `--boot --generation 1 --qualification-sha256 <sha>`; then `--quiesce`.
|
||||
- A prepared run is pinned to source hashes. Never modify tracked sources
|
||||
between prepare/qualification and boot.
|
||||
- RAM-scanned plug-in log lines can persist across boots: filter by the
|
||||
current run stamp, or old messages will contaminate diagnosis.
|
||||
- Reproduce userspace and Metal behavior offline on the matching macOS host
|
||||
via the interposed Metal plug-in and harnesses before testing on-device.
|
||||
- Use only a run's actual performance windows for FPS/latency reporting.
|
||||
Measurements during GPU latch, recovery or incomplete runs are invalid.
|
||||
|
||||
## Debugging notes
|
||||
## Agent Handoff Format
|
||||
|
||||
- Plug-in log lines found by RAM scans persist across boots. Filter them by
|
||||
the run's stamp, or you will chase an older run.
|
||||
- The macOS host is the same build as the guest, so most userspace and Metal
|
||||
failures reproduce offline. Interpose the default `MTLDevice` with the
|
||||
plug-in and replay there before using hardware.
|
||||
- Report fps and latency only from the run's perf windows. Never use numbers
|
||||
measured while the GPU is latched or recovering.
|
||||
When finishing a task, provide a compact report with these headings:
|
||||
|
||||
```
|
||||
Changes: [files and why]
|
||||
Validation: PASS [command]; FAIL [command/reason];
|
||||
SKIP [unavailable prerequisite]; NOT RUN [reason]
|
||||
Risks / limitations: [hardware, ABI, migration or reproducibility caveats]
|
||||
Hardware status: NOT RUN unless an authorized, recorded run actually occurred
|
||||
```
|
||||
|
||||
Never turn `SKIP` or `NOT RUN` into `PASS`, and never claim a successful PR,
|
||||
commit, merge, benchmark, boot or hardware qualification unless it happened.
|
||||
Reference in new issue
Block a user