Bare `throw new Error(...)` surfaces to users as code UNKNOWN with a
generic hint. Convert the remaining user-reachable clusters from the
July 2026 error audit to AppError with the right code, preserving
messages:
- metro/client-metro.ts: timeouts, bridge failures, and Metro start /
not-ready errors are now COMMAND_FAILED (the not-ready error also
carries logPath in details); createMetroBridgeRequestError builds on
AppError so non-retryable bridge errors that escape via rethrow get
the right code too
- mcp/command-tools.ts + mcp/router.ts: MCP input validation is now
INVALID_ARGS (JSON-RPC responses unchanged; the router only reads
.message)
- commands/batch/metadata.ts: step validation is now INVALID_ARGS;
with the plain-Error opt-out gone, the now-unused
BatchStepErrorFactory injection seam is removed from
batch-contract.ts
- cloud-webdriver/webdriver-source.ts: xml.ts parser failures are
wrapped at the consumer boundary into a single COMMAND_FAILED naming
what was being parsed
Relocate the central contracts barrel into the kernel/ dependency sink
alongside device/errors/redaction/snapshot (kernel now owns the pure
domain types per plans/perfect-shape.md §5.5).
- src/contracts.ts -> src/kernel/contracts.ts (git rename)
- repoint all 44 internal importers to ../kernel/contracts.ts
- rslib entry keeps key 'contracts' so dist output stays dist/src/contracts.js;
the public 'agent-device/contracts' subpath is byte-identical (proven by the
metro precedent in #947 and verified via build + package-exports test)
- update .fallowrc.json entrypoint + fallow-baselines/health.json key
Behaviorless path codemod (49 files, +57/-57). typecheck/lint/build/fallow
audit/public-contract tests all green.
* refactor: move errors/redaction/device into src/kernel — Phase 5 slice 3
Relocates the foundational primitive trio from src/utils/ into the kernel/ layer
(joining snapshot.ts from slice 2), per the target folder DAG in
plans/perfect-shape.md §5.5. A pure path codemod, no behavior change.
They form a closed cluster — device -> errors -> redaction, with redaction a
leaf — so kernel/ takes no upward dependency, and every importer becomes a clean
downward import toward kernel. errors.ts is the most-imported module in the
tree; device.ts the §5.5-named headliner. Moving all three atomically avoids a
half-state where one would import another across the utils/kernel boundary.
Imports rewritten by a resolve-based codemod (compares each specifier's resolved
path to the moved files, so the unrelated commands/management/device.ts and
other same-named files are untouched): 483 sites across 402 files. The two
platform-descriptor doc comments and the fallow health baseline key for
device.ts are updated to the new path; the contracts-schema-public guard that
asserts the error helpers pull no diagnostics/node: deps now reads kernel/.
Verified: tsc --noEmit, oxfmt + oxlint --deny-warnings, rslib build, full vitest
suite (2877 pass), fallow audit clean (411 changed files), Layering Guard empty;
kernel/ files import only within kernel.
* docs: update guidance references to kernel/{device,errors} after the move
AGENTS.md (Apple-family sync rule + normalizeError), ADR-0009, and
plans/apple-platform-consolidation.md still named the old src/utils/ paths.
Point them at src/kernel/. plans/perfect-shape.md's utils/device.ts mention is
left as-is — it describes the pre-move diagnosis.