Unit Standards — Engineer Review
Canonical standards, release-gate protocol, engineer handover template, and docs-archive discipline. The reference set every Unit module is built and locked against.
Standards Library Overview
The Unit Standards Library is the source of truth for how every Unit module is designed, implemented, previewed, tested, documented, reviewed, and handed off. Standards are not optional guidance — they define how work is accepted.
Purpose
Define the binding rules for module delivery: visual rules (UDSP), component contracts (Component Library), release-gate verification (preview-release-gate), engineer handover documentation (engineer-handover-template), and header / path doctrine. Each standard is canonical, append-only, and enforced as a release-gate BLOCKER on violation.
Canonical location
All standards live under
unit-app-system-library/01-STANDARDS/. Execution work
lives under unit-lab/. The system library is the source
of truth; unit-lab/ is the execution workspace.
Standards are never duplicated inside unit-lab/.
Current canonical standards
| File | Version | Authority | Scope |
|---|---|---|---|
| UNIT-UI-DESIGN-SYSTEM-PROTOCOL.md | v2.2 | GLOBAL STANDARD (NON-NEGOTIABLE) | Tokens, typography, spacing, error model, content & hierarchy discipline. |
| UI-COMPONENT-LIBRARY-STANDARD.md | v2.0 | GLOBAL STANDARD (NON-NEGOTIABLE) | 19 catalogued components with module classification + per-component enforcement. |
| preview-release-gate.md | v2.3 | GLOBAL STANDARD (NON-NEGOTIABLE) | Verify-all pipeline, release-gate report, engineer handover protocol, docs archive discipline. |
| engineer-handover-template.md | v1.1 | GLOBAL STANDARD (NON-NEGOTIABLE) | 16-section handover structure for LOCKED modules + docs structure contract. |
| global-header-path-doctrine.md | v2.0 | GLOBAL STANDARD (NON-NEGOTIABLE) | Required headers, repo-relative paths only, append-only Author History. |
| UI-CLAUDE-PROMPT-TEMPLATE.md | v2.0 | GLOBAL STANDARD (NON-NEGOTIABLE) | Canonical prompt block for AI-assisted UI work. |
| UI-CANONICALIZATION-REPORT.md | v1.0 | REPORT (READ-ONLY) | Records the 2026-04-28 migration of UI standards into the system library. |
| how-to-use-the-standards-library.md | v1.0 | USAGE GUIDE | Read-this-first guide for engineers, reviewers, integrators. |
How engineers use this library
verify:all exits 0, screenshots regenerated this pass, forbidden patterns absent, no unrelated modules touched.UI Design System Protocol v2.2
Source: UNIT-UI-DESIGN-SYSTEM-PROTOCOL.md v2.2. The
protocol binds every wallet module — Send, Deposit, Withdraw, Receive,
Activity, Dashboard. Every rule is a release-gate
BLOCKER or
REJECT on violation.
Token-only rule
All colors come from import { color } from 'design-system/tokens';
no raw hex outside colors.ts. All spacing comes from the
closed space.s* scale. All radii from
radius.{xs / sm / md / lg / xl / xxl / full}. All shadows
from named tokens. Single approved gradient: gradient.primary
on the primary CTA only. No inline color/spacing literals; no Tailwind
color classes.
Enforcement
Violation Inline style={{ color: '...' }}, off-scale spacing, or Tailwind colour class detected by source-scan.
Response BLOCKER — release gate fails. PR rejected.
Resolution Replace with token. If no token exists, propose one at the tokens layer (UDSP v1.1) before implementing.
Typography
Font sizes come from the closed scale:
displayXL: 44, displayLG: 36,
displayMD: 32, displaySM: 28,
titleLG: 22, titleMD: 18,
bodyLG: 17, bodyMD: 16,
bodySM: 15, metaLG: 14,
metaMD: 13, metaSM: 12,
metaXS: 11. Line heights from
display: 1.02 / tight: 1.08 / snug: 1.20 / normal: 1.40.
Weights and tracking from typography.ts named values.
Spacing
All padding, margin, gap, and
offsets use space.s* from the closed scale
s4 / s6 / s8 / s10 / s12 / s14 / s16 / s18 / s20 / s22 / s24 / s28 / s32 / s40.
s40 is reserved for screen-edge padding only. Off-scale
spacing is BLOCKER.
Error-state model (v2.2 — minimal product standard)
Error renders as a content state, not a container or alert box. It replaces the primary surface while preserving the overall layout structure.
| Element | Token / rule |
|---|---|
| Container | border: none, background: transparent, no border-radius framing |
| Background fill | FORBIDDEN — color.errorSoft as a surface fill is not allowed |
| Border | FORBIDDEN — zero borders inside the error block |
| Chromatic signal | Single error dot above headline |
| Headline | titleMD · color.textStrong — neutral, never red |
| Body | bodySM · color.textBody — neutral, never red |
| "Reason" eyebrow | NEVER RENDERED |
| Retry button | NEVER RENDERED unless explicitly defined in spec |
| Tone copy | Calm, instructional, single line. No "Something went wrong". No raw enums. |
Principle. Error is a state of the same product — not a system alert or interruption.
Content & hierarchy discipline (§12)
Ten enforcement rules codifying Apple-level minimalism. Each rule binds as a release-gate BLOCKER or REJECT.
Receive, Send). Forbidden: "Scan to receive", "Enter amount to send", "Click Continue", "Tap to copy". REJECTspace.s* scale and serve a purpose. REJECTComponent Library Standard v2.0
Source: UI-COMPONENT-LIBRARY-STANDARD.md v2.0. 19
catalogued components, each carrying a Module Classification table
(Send / Deposit / Withdraw / Receive: REQUIRED / OPTIONAL /
FORBIDDEN / N/A) and a 4-row enforcement table.
Approved component categories
| # | Component | Status | Reference |
|---|---|---|---|
| 1 | PageShell | EXTRACTED | DepositStepOne.tsx page+shell+body |
| 2 | StepContainer | EXTRACTED | DepositStepOne.tsx + WithdrawStepOne.tsx card |
| 3 | SectionHeader | EXTRACTED | DepositStepOne.tsx titleBlock + headerRow |
| 4 | AssetSelector | EXTRACTED | DepositStepOne.tsx SelectShell |
| 5 | AmountInput | EXTRACTED | DepositStepOne.tsx amountHero + amountInput |
| 6 | QuickFillControls | EXTRACTED | WithdrawStepOne.tsx quick-fill grid |
| 7 | AddressCard | EXTRACTED | DepositStepTwo.tsx addressBox |
| 8 | QRBlock | EXTRACTED | DepositStepTwo.tsx qrFrame + qrInner |
| 9 | ReviewSummary | EXTRACTED | DepositStepOne + ReviewWithdrawal summary |
| 10 | StatusPanel | EXTRACTED | DepositStepTwo.tsx statusBlock |
| 11 | CTAButton | EXTRACTED | DepositStepOne.tsx cta + ctaDisabled |
| 12 | SecondaryButton | EXTRACTED | DepositStepThreeCancelled.tsx secondaryCta |
| 13 | ValidationMessage | EXTRACTED | DepositStepOne.tsx helper |
| 14 | CopyAction | EXTRACTED | DepositStepTwo.tsx copyButton |
| 15 | NetworkLabel | EXTRACTED | WithdrawStepOne.tsx networkBadge |
| 16 | EmptyState | EXTRACTED · GAP | DepositStepOne empty-asset; Receive.tsx skeleton |
| 17 | LoadingState | EXTRACTED · GAP | Receive.tsx skeleton (live app) |
| 18 | ErrorState | EXTRACTED | DepositTxHashFlow + WithdrawalTerminal Failed |
| 19 | SuccessState | EXTRACTED | DepositStepThreeCompleted + WithdrawalTerminal Completed |
Module classification matrix
| Component | Send | Deposit | Withdraw | Receive |
|---|---|---|---|---|
| PageShell | REQ | REQ | REQ | REQ |
| StepContainer | REQ | REQ | REQ | REQ |
| AmountInput | REQ | REQ | REQ | N/A |
| QuickFillControls | REQ | FORBIDDEN | REQ | N/A |
| QRBlock | FORBIDDEN | REQ | FORBIDDEN | REQ |
| AddressCard | OPT | REQ | REQ | OPT |
| StatusPanel | OPT | REQ | REQ | N/A |
| CopyAction | OPT | REQ | REQ | REQ |
| LoadingState | REQ | REQ | REQ | REQ |
| SuccessState | REQ | REQ | REQ | N/A |
Forbidden inventions
Engineers MUST NOT invent new patterns at the implementation layer. If a required pattern is not catalogued, mark GAP in the module's audit, propose at the standards layer, implement only after the catalog is updated. Implementation-layer invention is REJECT.
Module compliance expectations
Every TSX component used by a module is traceable to an entry in this standard. A component appearing in module TSX without a catalog entry, or with a contract that diverges from the catalog, is REJECT.
Preview Release-Gate Protocol v2.3
Source: preview-release-gate.md v2.3. Binds every
module's verification pipeline. A module is not eligible for engineer
handover until verify:all exits 0 from a clean checkout.
Manual screenshot placement is banned.
The verify:all pipeline
Every module exposes a single canonical entry point at
handover/tests/package.json. verify:all MUST
execute, in order:
npm installresolve dependenciesnpm run install:browsersplaywright install chromiumnpm run capture:previewcapture-preview.mjs · zero console / pageerrornpm run verify:screenshotsverify-screenshots.mjs · closed-set inventorynpm run testplaywright + source-scanScreenshot capture
capture-preview.mjs probes localhost:5173,
spawns Vite if unreachable, captures every required PNG for the
module's canonical state set, prints inventory, exits non-zero on any
capture failure, any pageerror, any
console.error, or any missing PNG.
Manual placement is BANNED
BLOCKER — every PNG must come
from capture-preview.mjs.
Playwright test suite
The Playwright suite must cover all six dimensions — no partial coverage permitted:
- Invariant compliance (assertions tied to the invariant map)
- UI correctness (every visible affordance per spec)
- All states (LOADING / READY / ERROR / closed set per module)
- Error model compliance (UDSP §7.3)
- Forbidden patterns (source-scan grep over TSX + preview HTML)
- Layout stability — no shift between LOADING and READY
Source-scan
Forbidden-pattern greps execute inside the test suite (step 5). Every forbidden token from the module's invariant map and from UDSP §9 must return zero matches. Common module forbidden lists:
- Deposit:
availableBalance,handlePercent,onPercentFill,quickFillDisabled,dpOnPercentFill, percentage / Max controls. - Withdraw (user-facing):
onSubmitTxHash,txHashSubmitted, "Submit/Paste/Enter transaction hash" copy,WithdrawTxHashSubmitCard(operator-only). - Receive: invite / invitee terminology, share buttons (WhatsApp / Telegram / X),
navigator.share,crypto_symbol,UNITCOIN, asset symbols.
Codebase audit
Each module produces
handover/docs/<module>-codebase-audit-report.md as a
precondition to release-gate. Audit verdict must be PASS before the
gate is initiated. Any precondition missing or in non-LOCKED /
non-PASS state is a BLOCKER —
release-gate execution refused.
Release-gate report
Each module produces
handover/docs/<module>-release-gate-report.md. The
report MUST include: executive summary (PASS / FAIL), commands
executed (with exit codes), test results (per group, with counts),
screenshot inventory (filename + size + verdict per PNG), source-scan
results, console / pageerror results, codebase audit reference, final
binary verdict, and any carried-forward advisories with explicit
non-blocker classification.
Soft verdicts ("partial PASS", "conditional PASS", "PASS with caveats") are REJECT — gate is not considered passed.
Docs archive discipline
v2.3 introduces §11.7 — before a module can pass release-gate, its
handover/docs/ directory MUST conform to a strict
three-tier classification (ACTIVE / CERTIFICATION / ARCHIVE). See
section 7 below for the full discipline.
Final completeness rule (§11.7.6 · supersedes §10.12 + §11.6)
A module is COMPLETE only when ALL FOUR hold:
1. verify:all exits 0
2. <module>-release-gate-report.md final verdict is PASS
3. <module>-engineer-handover.md exists and conforms to §11.3
4. <module>/handover/docs/ conforms to the docs-archive discipline declared in §11.7
Until all four hold, the module is NOT complete. The STATUS line
MUST NOT read LOCKED — WORLD-CLASS STANDARD.
Engineer Handover Standard v1.1
Source: engineer-handover-template.md v1.1. Every LOCKED
module produces
<module>/handover/docs/<module>-engineer-handover.md
following the canonical 17-section structure. Authored after
release-gate PASS and before the LOCK STATUS line.
Required handover document
Path:
<module>/handover/docs/<module>-engineer-handover.md.
The document is the entry point for any engineer picking up a LOCKED
module — it binds the implementation contract end-to-end with zero
ambiguity.
Required sections (16 sections + Author History)
| § | Section | Required content |
|---|---|---|
| 0 | Header | Module / STATUS / invariant-map version / execution-spec version / TSX layer / preview / test suite / audit / release-gate — all populated |
| 1 | Module Summary | One-paragraph summary + "What does NOT do" exclusions table |
| 2 | File Structure | Full module file tree + role table |
| 3 | Core Data Model | All closed types verbatim from <module>Types.ts |
| 4 | Rendering Contract | Zone order + canonical-value declaration + header content |
| 5 | State Definitions | One sub-section per closed state (LOADING / READY / ERROR / GAP) |
| 6 | Invariant Rules | Numbered list with rule + authority citation |
| 7 | Forbidden Patterns | Numbered list with pattern + reason citation |
| 8 | Styling Rules | Token-only rules + typography token table + advisories |
| 9 | Error Model | UDSP v2.2 §7.3 model statement + tone copy rules |
| 10 | Test Coverage | Test-group table with counts + dimensions + spec citation |
| 11 | Screenshot Inventory | Closed N-PNG set with route mapping |
| 12 | Release-Gate Requirements | verify:all 5-step pipeline + STATUS-line advance rules |
| 13 | Known Advisories | Each advisory with location + issue + resolution path + Impact on LOCK: NONE |
| 14 | Implementation Guardrails | Numbered FORBIDDEN list + escalation chain |
| 15 | QA Checklist | Numbered checks with verification method |
| 16 | Final Statement | LOCKED principle + three-situations clause |
Docs structure contract (v1.1 addition)
v1.1 adds the Docs Structure Contract section after §2 of the
template body. The <module>/handover/docs/
directory follows the three-tier classification declared in
preview-release-gate.md §11.7 — see section 7 below.
Implementation guardrails (§14)
Once a module is LOCKED, the following changes are
FORBIDDEN against it. Each is a release-gate
BLOCKER and a doctrinal
violation under preview-release-gate.md §10.10:
To make any of these changes, amend the relevant authority layer first (invariant map → execution spec → standards), with a versioned LOCK pass at each layer, then re-run the full release gate. Implementation-layer changes that contradict a locked layer are drift, not progress.
QA checklist (§15)
console.error / pageerror across all routes — capture-preview.mjs exit 0verify-screenshots.mjs PASSnpm run test exit 0npm run verify:all exits 0 — single-command runPASS — release-gate reportLOCKED — WORLD-CLASS STANDARD + LOCK Author History row — STATUS.md current stateNo soft language
The handover MUST NOT contain soft language —
should, may, likely,
expected, possibly, might.
Any presence is a BLOCKER.
Use protocol-style wording: is, MUST,
MUST NOT, renders, imports,
is gated by.
Docs Archive Discipline (§11.7)
Source: preview-release-gate.md v2.3 §11.7 +
engineer-handover-template.md v1.1 (Docs Structure
Contract). Before a module can pass release-gate, its
handover/docs/ directory MUST conform to a strict
three-tier classification.
Required structure
<module>/handover/docs/
├── README.md docs index — entry-point pointer
├── <module>-engineer-handover.md ACTIVE · entry point
├── <module>-invariant-map.md ACTIVE · LOCKED invariants
├── <module>-live-codebase-extraction.md ACTIVE · live-app baseline
├── <module>-codebase-audit-report.md CERTIFICATION · audit verdict
├── <module>-release-gate-report.md CERTIFICATION · release-gate
└── archive/
├── <module>-*-delivery.md historical · closeout records
├── <module>-*-refinement-*.md historical
└── <other delivery / refinement / intermediate artifacts>
Three-tier classification
| Tier | Lives at | Contents |
|---|---|---|
| ACTIVE | docs root | Engineer handover, invariant map, live-codebase extraction. Read by anyone implementing, auditing, or extending the module. |
| CERTIFICATION | docs root | Codebase audit report, release-gate report, docs-discipline cleanup report. Immutable evidence of single passes. |
| ARCHIVE | archive/ |
Delivery notes (*-delivery.md), refinement notes, intermediate artifacts, superseded drafts. Retained for traceability; never source of truth. |
Forbidden at docs root
| Forbidden | Reason |
|---|---|
Delivery files (*-delivery.md) | Historical records, not source of truth — belong in archive/ |
Refinement notes (*-refinement-*.md) | Historical — belong in archive/ |
| Duplicate authority docs (e.g. two invariant maps) | The LOCKED authority chain permits exactly one canonical document per role |
| Files of unclear purpose | Every doc-root file maps to ACTIVE or CERTIFICATION; ambiguity is a documentation BLOCKER |
| Missing README.md docs index | Engineers MUST have a single entry pointer to the module's docs |
| Mixing archive content into active root | Tier separation is binding |
README requirement
README.md MUST exist at the docs root and MUST cite
preview-release-gate.md §11.7 as the binding standard.
It MUST index every ACTIVE + CERTIFICATION doc with a one-line role
description for each. The README also explains the
archive/ contents at a high level.
No deletion rule
The cleanup pass MUST NOT delete any file. Historical artifacts are
moved via git mv from the docs root into
archive/. Zero file deletions, zero file content
modifications. The cleanup is structural-only.
Enforcement
Docs-archive discipline
Violation Any of: archive/ subdirectory missing; delivery file at root; refinement note at root; README.md missing or stale; ambiguous file at root; duplicate authority doc at root.
Response BLOCKER — module cannot pass release-gate. The §11.6 completeness rule is not satisfied.
Resolution Create archive/. git mv the delivery / refinement files into it. Author or refresh README.md citing this §11.7 standard. Re-validate.
Validation command
find <module>/handover/docs -maxdepth 2 -type f
Expected at root: README.md + the 5 ACTIVE/CERTIFICATION
docs + (optionally) a one-time docs-cleanup report. Expected under
archive/: every other historical artifact. Anything else
at root is a violation.
Global Header + Path Doctrine v2.0
Source: global-header-path-doctrine.md v2.0. Defines the
mandatory header, path, and validation rules for all Unit Lab
artifacts. No document or code file is handover-ready until it
complies.
GitHub paths only
Every authored artifact (.md, .tsx,
.ts, .html, .mjs,
.js) carries a Path / Source block with both a
repo-relative path and a GitHub URL. Local absolute paths are
forbidden in checked-in artifacts.
No local paths
Forbidden anywhere in checked-in content:
/Users/...
/home/...
~/...
<HOME>/...
C:\Users\...
Required path format:
Path:
- Repo: <repo-relative-path>
- GitHub: https://github.com/UNITNETWORKECOSYSTEM/unit-lab/tree/main/<repo-relative-path>
Required header fields (Markdown)
| Field | Rule |
|---|---|
| Title | # <Module> — <Document Title> |
| Version | v<x.y> |
| Last Updated | YYYY-MM-DD |
| Path | Repo + GitHub block (no local paths) |
| Authority Level | e.g. GLOBAL STANDARD, MODULE INVARIANT, ENGINEER HANDOVER |
| Status | DRAFT / ACTIVE / LOCKED / FINAL / DEPRECATED |
| Workspace | unit-lab or unit-app-system-library |
| Module | Module name (or "global") |
Author History rules
Every authored Markdown file carries an
## Author History table directly after the header
divider:
- Author rules: initials only (e.g.
SL). No full names. No AI attribution. - Role enum: Spec Owner · Reviewer · Engineer · Auditor
- Change-Type enum: CREATE · UPDATE · CORRECTION · MIGRATION · LOCK · DEPRECATE
- Summary rule: one line, factual only, no narrative.
- Structure: append-only. Newest rows appended at bottom. No row mutation, no row deletion.
Code header standard
/**
* Module: <Module>
* File: <repo-relative-path>
* Authority Level: <LEVEL>
* Purpose: <one-line purpose>
* Status: <ACTIVE | LOCKED | FINAL>
*
* Source:
* - Repo: <repo-relative-path>
* - GitHub: https://github.com/UNITNETWORKECOSYSTEM/unit-lab/tree/main/<repo-relative-path>
*
* Rules:
* - Do not use local absolute paths.
* - Do not change behavior without updating the governing execution spec.
*/
Validation
grep -RIn "/Users/" <module>/ \
--exclude-dir=node_modules \
--exclude-dir=dist \
--exclude-dir=.next \
--exclude-dir=build || true
Expected result: zero forbidden user-absolute paths across authored artifacts. Dependency folders are excluded.
Engineer Workflow — Module Lifecycle
The exact lifecycle every Unit module goes through, from spec to LOCK. Each stage produces required artifacts; lower stages cannot proceed until upper stages PASS.
STATUS line advance
After successful release-gate execution, STATUS.md
advances through exactly two STATUS lines:
RELEASE GATE PASSED — READY TO LOCK(Author History change-typeVERIFY)LOCKED — WORLD-CLASS STANDARD(Author History change-typeLOCK)
Skipping the verify line, mutating either Author History row, or advancing to LOCKED before stages 6 + 7 complete is a BLOCKER.
Receive — First Reference Implementation
Receive is the first Unit module to reach
LOCKED — WORLD-CLASS STANDARD under the full v2.3
protocol. It is the canonical reference for every subsequent module.
The module's own docs live at
unit-lab/receive/handover/docs/.
Receive's docs directory at
unit-lab/receive/handover/docs/ is the reference
implementation of §11.7 docs-archive discipline: 4 active /
certification docs at root, README.md docs index, 4
delivery files moved to archive/. Use Receive as the
worked example when applying this protocol to a new module.