Skip to content

feat(v0.14.3): three new decoders — u16_fiftieths, u32_be, u16_half - #185

Merged
ohgeeceee merged 1 commit into
mainfrom
v0.14.3-slice1-decoders
Jul 30, 2026
Merged

feat(v0.14.3): three new decoders — u16_fiftieths, u32_be, u16_half#185
ohgeeceee merged 1 commit into
mainfrom
v0.14.3-slice1-decoders

Conversation

@ohgeeceee

Copy link
Copy Markdown
Owner

Slice 1 of v0.14.3 — "Finish the Bench"

Cycle plan: docs/v0.14.3_plan.md. Tier A only (Rust + docs). No transport/** / protocol/** / commands.rs changes, no new crate, no new Tauri command.

What this slice ships

Three new decoders the v0.14.2 slice 1 PR (#175) explicitly deferred pending new decoders:

Decoder Formula SAE J1979 PID Use case
u16_fiftieths raw × 0.02 OBD 0x5E Engine fuel rate (L/h) — N62 ME9.2 + every other OBD-II ECU
u32_be raw as f64 OBD 0x5F Engine runtime since start (s) — first non-u16 numeric decoder in the catalog
u16_half raw × 0.5 OBD 0x62 Engine fuel rate (g/s) — N62 ME9.2 + every other OBD-II ECU

Each follows the existing u16_div100 / u16_tenths / u16_milli family shape: same 2-byte BE minimum contract (u32_be has its own 4-byte guard), same short-buffer safety, same TOML string ↔ enum round-trip (decode_from_strdecode_to_str).

Files

  • src-tauri/src/data/live.rs:
    • Decode enum: three new variants with doc-comments spelling out SAE J1979 scale + N62/E70 use case.
    • decode() match arm: u16_fiftieths + u16_half join the existing 2-byte family block; u32_be stands alone with its own 4-byte guard.
    • decode_from_str + decode_to_str: three new TOML strings + enum variants. Round-trip test grows three rows to pin them.
    • tests: 3 new per-decoder tests + 1 new u32_be_short_buffer test. The existing u16_family_short_buffer test grows two rows for the new u16 family members.
  • docs/DECODE_FUNCTIONS.md:
    • New §10 / §11 / §12 sections spelling out formula, input/output contract, OBD PID mapping, range, and v0.14.3 cycle reference for each new decoder.
    • "Last updated" footer bumped to 2026-07-30 + slice pointer.

Verification

  • cargo test --offline --lib data::live — 32/32 pass.
  • cargo test --offline --lib — 142/142 pass (full src-tauri suite, no regressions).
  • cargo check --offline — clean. Pre-existing commands.rs / sim.rs / protocol/** clippy warnings remain; none introduced by this PR.
  • cargo fmt --check src/data/live.rs — clean.
  • node --test src/js/**/*.test.{js,cjs} — 221/221 pass (no JS changes).
  • node scripts/lint-toml.js — 37/0 clean (no TOML changes; profile entries land in slice 2).

Tier

A. Self-merge when CI is green.

Slice 1 of v0.14.3 'Finish the Bench'. Tier A only (Rust + docs).
The cycle plan narrowed v0.14.3 slice 1 to just these three
decoders; each is needed by an OBD-II SAE J1979 PID the v0.14.2
N62 slice 1 PR (#175) explicitly deferred pending new decoders.

Decoders added:

- **`u16_fiftieths`** — raw × 0.02 (2 bytes BE → f64). For
  SAE J1979 PID 0x5E engine fuel rate (L/h). raw 50 = 1.00 L/h,
  raw 65535 ≈ 1310.70 L/h.
- **`u32_be`** — 4-byte BE unsigned as f64 (no scale). For SAE
  J1979 PID 0x5F engine runtime since start (seconds). raw 0 =
  cold start, raw 0xFFFFFFFF ≈ 4.29e9 s (~136 years — overflow
  sentinel). First non-u16 numeric decoder in the catalog;
  opens the door to OBD PIDs that need higher precision / range
  than 16 bits (future odometer, fuel totals, durations).
- **`u16_half`** — raw × 0.5 (2 bytes BE → f64). For SAE J1979
  PID 0x62 engine fuel rate (g/s). raw 2 = 1.00 g/s, raw 65535
  ≈ 32767.50 g/s.

Decoder shape matches the existing u16_div100 / u16_tenths /
u16_milli family: same 2-byte BE minimum contract, same
short-buffer safety, same TOML name ↔ enum round-trip
(`decode_from_str` ↔ `decode_to_str`).

Files:

- `src-tauri/src/data/live.rs`:
  - Decode enum: three new variants (`U16Fiftieths`,
    `U32Be`, `U16Half`) with doc-comments spelling out the
    SAE J1979 scale and the typical N62/E70 use case.
  - `decode()` match arm: u16_fiftieths and u16_half join the
    existing 2-byte family block (the same short-buffer guard
    handles all 9 u16 variants); u32_be stands alone with its
    own 4-byte guard.
  - `decode_from_str` + `decode_to_str`: three new
    "u16_fiftieths" / "u32_be" / "u16_half" strings +
    their enum variants. The TOML string ↔ enum round-trip
    test grows three rows to pin them.
  - tests: 3 new per-decoder tests (u16_fiftieths,
    u16_half, u32_be) covering scale edge cases (0, mid-range,
    saturation, sign-relevant cases for u32). 1 new test for
    u32_be short-buffer safety. The existing
    `u16_family_short_buffer` test grows two rows for the
    new u16 family members.
- `docs/DECODE_FUNCTIONS.md`:
  - New §10 / §11 / §12 sections (after the v0.7.0 §9
    `[profile.theme]` block, before the contributor checklist)
    spelling out the formula, input/output contract, OBD PID
    mapping, range, and v0.14.3 cycle reference for each new
    decoder.
  - "Last updated" footer bumped to 2026-07-30 + slice
    pointer.

Verification:

- `cargo test --offline --lib data::live` — 32/32 pass
  (was 28 + 3 new per-decoder tests + 1 new short-buffer test
  for u32_be; the existing u16_family_short_buffer grew two
  rows but it's still one test).
- `cargo test --offline --lib` — 142/142 pass (full
  src-tauri suite, no regressions).
- `cargo check --offline` — clean (only pre-existing
  `commands.rs` / `sim.rs` / `protocol/**` clippy warnings
  remain, none introduced by this PR).
- `cargo fmt --check src/data/live.rs` — clean.
- `node --test src/js/**/*.test.{js,cjs}` — 221/221 pass
  (no JS changes; baseline unaffected).
- `node scripts/lint-toml.js` — 37/0 clean (no TOML changes;
  the profile entries land in slice 2).

Tier

A. Self-merge when CI is green.
@ohgeeceee
ohgeeceee merged commit 9d8d0b9 into main Jul 30, 2026
10 of 11 checks passed
@ohgeeceee
ohgeeceee deleted the v0.14.3-slice1-decoders branch July 30, 2026 01:54

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c9f56d22a6

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +47 to +50
/// u32 BE raw as f64 — SAE J1979 PID 0x5F engine runtime since
/// start (seconds). 4-byte big-endian unsigned; max ~4.29e9 s
/// (~136 years — far exceeds any real engine's lifetime).
/// Used for OBD 0x5F (engine_runtime).

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Map engine runtime to PID 0x1F instead

For SAE J1979 Mode 01, PID 0x5F is the one-byte vehicle emissions-requirements field; runtime since engine start is PID 0x1F, encoded as two big-endian seconds bytes. Because read_obd_pid passes only the response data to decode, the planned 0x5F profile entry will supply one byte and U32Be will return None, so the runtime gauge will never receive a sample. Keep U32Be generic if needed, but do not associate it with 0x5F; model runtime using the 0x1F payload.

Useful? React with 👍 / 👎.

Comment on lines +52 to +54
/// u16 BE * 0.5 — SAE J1979 PID 0x62 engine fuel rate (g/s).
/// Scale = 1/2; raw 2 = 1.00 g/s; raw 65535 = ~32767.5 g/s.
/// Used for OBD 0x62 (engine_fuel_rate_gs).

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Decode PID 0x62 as actual engine torque

For SAE J1979 Mode 01, PID 0x62 is actual engine percent torque, encoded in one byte as A - 125, not a two-byte fuel-rate value scaled by 0.5. The planned profile entry will therefore pass a one-byte payload to U16Half, which returns None, preventing the gauge from producing a value; this PID needs a one-byte offset decoder and torque labeling instead.

Useful? React with 👍 / 👎.

Decode::U16Times10 => raw * 10.0,
Decode::U16Tenths => raw * 0.1,
Decode::U16Div100 => raw * 0.01,
Decode::U16Fiftieths => raw * 0.02,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Scale PID 0x5E fuel rate by one twentieth

SAE J1979 Mode 01 PID 0x5E defines engine fuel rate as (256*A + B) / 20 L/h, so the multiplier must be 0.05, not 0.02. When the planned N62 profile starts using this decoder, every displayed fuel-rate sample will be only 40% of its actual value (for example, raw 100 should be 5 L/h but this returns 2 L/h), corrupting the gauge and exported snapshots.

Useful? React with 👍 / 👎.

ohgeeceee added a commit that referenced this pull request Jul 30, 2026
…ntime PIDs (#186)

Slice 2 of v0.14.3 'Finish the Bench'. Tier A only (data). Depends
on slice 1 (PR #185) for the `u16_fiftieths` / `u32_be` /
`u16_half` decoders — without them, shipping these profile entries
breaks every consumer at load time with `unknown decode: X`.

The decoder-first discipline from the v0.14.2 N62 slice 1 PR (#175)
is preserved: each new entry's doc-comment spells out the SAE J1979
PID, the decoder formula, expected idle / WOT ranges, and the
bench-verification path on the E70 (the v0.14.2 slice 3 harness doc
${docs/validation/n62-real-car.md\}'s Step 2 cold reading table grows
three rows in v0.14.3 slice 4).

New profile entries:

- `fuel_rate_lh` — SAE J1979 PID `0x5E` engine fuel rate (L/h),
  `u16_fiftieths` (raw × 0.02). Idle on a warm N62 ~1-2 L/h;
  WOT ~50-90 L/h. Range capped at 100 L/h — well above the
  scale top end for a V8 (raw 65535 ≈ 1310 L/h, which is the
  saturated / fault sentinel).
- `engine_runtime` — SAE J1979 PID `0x5F` engine runtime since
  start (seconds), `u32_be` (4-byte BE unsigned). Range covers
  the full u32 domain (0 to 4.29e9 s ≈ 136 years); the
  `0xFFFFFFFF` overflow sentinel caps at the engine's actual
  lifetime. Resets on each ignition cycle.
- `fuel_rate_gs` — SAE J1979 PID `0x62` engine fuel rate (g/s),
  `u16_half` (raw × 0.5). Idle on a warm N62 ~1-2 g/s;
  WOT ~40-70 g/s. The load-bearing PID for BSFC
  (brake-specific fuel consumption) heuristics — divide by
  RPM × cyl_count for instantaneous BSFC.

Files:

- `community/profiles/n62.toml`:
  - header: new "Fuel-rate + runtime notes (v0.14.3)" block
    spelling out the three SAE J1979 PIDs + bench-verification
    gate.
  - three new `[[profile.param]]` entries with evidence
    markers (per the data-discipline convention in
    `docs/DECODE_FUNCTIONS.md` §1): SAE J1979 PID provenance,
    decoder formula, expected idle / WOT ranges, the
    harness-doc verification path.

Verification:

- `node scripts/lint-toml.js` — 37/0 clean.
- `node --test src/js/**/*.test.{js,cjs}` — 221/221 pass
  (no JS changes).
- No Rust / Cargo changes; `cargo check` clean.
- No new crate, no new Tauri command.

Tier

A. Self-merge when CI is green.

Co-authored-by: ohgeeceee <ohgeeceee@users.noreply.github.com>
github-actions Bot pushed a commit that referenced this pull request Jul 30, 2026
docs/validation/n62-real-car.md: add the three v0.14.3 PIDs
(0x5E fuel rate L/h, 0x5F engine runtime s, 0x62 fuel rate g/s)
to Step 2 cold-reading + Step 3 running-reading tables. Add
critical-row paragraph for fuel-rate failure modes. Extend
Step 4 report template + Step 5 consequences. Update
cross-references to point at PRs #185/#186/#187 and
docs/DECODE_FUNCTIONS.md sections 10-12.

ROADMAP.md: close v0.14.3 cycle table (slices 1, 2, 3a, 4 done;
slice 3b frontend rewire still open). Bump "Last updated"
header. Correct the stale v0.14.2 cycle-table notes that said
the deferred PIDs were v0.14.3+ work (they ship in v0.14.3).

CHANGELOG.md: add the first entry since v0.14.0 — marked
"Unreleased" because slice 3b is still open and the v0.14.3
release cut cannot happen until slice 3b merges. Notes on the
version surface explain why the README badge stays at v0.14.0
(CLAUDE.md golden rule #5: don't let the badge lie about an
incomplete cycle). Also flags v0.14.1 and v0.14.2 as missing
CHANGELOG entries; the maintainer's housekeeping follow-up is
the appropriate scope for that backfill.

Tier A (docs only). No code changes, no transport/** changes,
no protocol/** changes. PR auto-merge eligible per CLAUDE.md
once CI is green.

Findings flagged (not fixed in this PR — Tier B surface, CLAUDE.md
golden rule #3: don't widen PR scope):
- src-tauri/src/data/live.rs::tests::remove_param_from_profile_is_idempotent
  fails on origin/main @ 093b063 (PR #187). Test asserts N-1 params
  after second remove; returns N. Likely HashSet ordering issue in
  the test fixture (not the production code path). Worth a
  separate Tier B fix PR.

Co-authored-by: ohgeeceee <ohgeeceee@users.noreply.github.com>
ohgeeceee added a commit that referenced this pull request Jul 30, 2026
…nfig-fix) (#189)

The review workflow's `claude-code-action@v1` (floating tag) has
been failing on every PR since at least 2026-07-29 with:

  Internal error: directory mismatch for directory
  "/home/runner/work/_actions/anthropics/claude-code-action/<ref>/tsconfig.json",
  fd 4. ... Claude result reported subtype success with is_error:true

Confirmed in the repo: 10 consecutive claude-review run failures
spanning the v0.14.2-slice3, v0.14.3-slice1/2/3, v0.14.3-doc-rot
and PRs #188 / #187 / #186 / #185 branches. The same SHA can succeed
on one run and fail on the next (per upstream issue
anthropics/claude-code-action#1266).

Upstream root cause: a Bun runtime bug that fires when the action
internally passes --tsconfig-override to bun. Fixed in
anthropics/claude-code-action#1315 (commit 232c9a15f4, 2026-06-09)
by dropping the --tsconfig-override flag from the three bun run
invocations in action.yml.

That fix IS in our current `@v1` resolution (verified SHA
be7b93b1907a4abad570368f3c74b6fe3807510b, dated 2026-07-25, latest
release v1.0.183). So the fix landed but the abort case still fires
on our ubuntu-24.04 runner — issue #1266 explicitly notes this is
environment-specific ("For some users this is a harmless stderr
warning; for others it aborts the action with exit code 1").

The smallest, most defensible change here: pin to the explicit
version that contains the upstream fix (v1.0.183, the latest at
this time) instead of the floating `@v1`. This makes the action
version reproducible, easy to bisect if it regresses, and easy to
bump when a confirmed-good release lands.

Past fix attempts in this repo:
- PR #173 (empty — abandoned)
- PR #174 (empty — abandoned)
- PR #176 (removed `Bash(gh pr review:*)` from --allowedTools —
  didn't fix the underlying issue, the bug has continued firing
  since)

Files changed (3):
- .github/workflows/claude-review.yml — the one that fires on every
  PR and is the visible failure PR #188 / PR #187 / etc all hit
- .github/workflows/claude.yml — Claude Code Action itself
- .github/workflows/claude-implement-issue.yml — Claude Code
  Implement Issue workflow

Tier A (CI workflows per CLAUDE.md). PR auto-merge eligible.

If the review check still fails after this lands, the next move
(documented for a follow-up PR, not in scope here) is either:
- Pin to a SHA explicitly confirmed working on ubuntu-24.04 runners
  (issue #1266 has a "known-good SHA" ask that wasn't answered)
- Swap to a different action family (e.g. claude-code-base-action
  has fewer internal bun invocations and doesn't trip the same bug)
- Disable the workflow trigger and rely on local agent dispatch,
  the workaround issue #1266's reporter ended up using

Verification:
- [x] Workflow YAML lints clean (CI lint step on the patch output)
- [x] v1.0.183 is the latest release at this time per
  https://github.com/anthropics/claude-code-action/releases
  (verified 2026-07-30)
- [x] Same SHA (`be7b93b1`) is what `@v1` resolves to currently,
  so this pin is functionally equivalent to the floating tag for
  today — but is now explicit and reproducible

Co-authored-by: ohgeeceee <ohgeeceee@users.noreply.github.com>
ohgeeceee added a commit that referenced this pull request Jul 31, 2026
Closes the v0.14.3 cycle for real. PR #188 (slice 4) closed
the cycle table on its own merge but the cycle itself was
incomplete — slice 3b was still open, gating the release cut.
PR #190 (slice 3b, merged 2026-07-30T18:58:11Z into
origin/main @ 10f58c8) closed that gate. This PR updates the
stale docs to match reality.

## What this PR ships

### ROADMAP.md

- "Last updated" header: bumped from "partial close" to
  "closed"; tier split bumped from "3 Tier A + 1 Tier B + 1 Tier B
  still open" to "3 Tier A + 2 Tier B + 0 Tier C"; all five cycle
  slices now listed as merged (#185, #186, #187, #188, #190).
- v0.14.3 cycle section header: "In Progress — slices 1, 2, 4
  done; slice 3 split" → "Shipped 2026-07-30".
- Cycle table slice 3b row: 🔲 Open → ✅ Done (PR #190), with
  full notes describing the `classifyNrc` helper, the per-PID
  dim + one-click-remove UI, the `#live-unsupported-count`
  panel-head badge, and the new `.gauge-cell.dimmed` /
  `.pid-remove` CSS.
- Cycle table other rows updated to attribute by PR number
  (#188) instead of the original "this PR" placeholder.
- Release-cut paragraph: "Cannot be cut until slice 3b
  merges" → "is a separate Tier C step — all five cycle slices
  are merged but the version-surface bump requires an explicit
  release-cut PR".

### CHANGELOG.md

- v0.14.3 "Cycle status" blockquote: bumped from "slices 1, 2,
  3a, 4 merged; slice 3b still open" to "all five slices
  merged — #185 (decoders), #186 (profile entries), #187
  (slice 3a backend), #188 (slice 4 harness extension + cycle
  closeout), #190 (slice 3b frontend rewire)".
- v0.14.3 "Added — Tier B surface" bullet: merged the slice 3a
  (PR #187) and slice 3b (PR #190) descriptions into a single
  "Per-PID NRC backend + frontend + remove-from-profile UI"
  entry with PR sub-bullets. Removed the now-stale "slice 3b is
  still open" note.
- v0.14.3 "Notes on the version surface" — README badge
  paragraph: rewrote to acknowledge slice 3b is now merged
  but the release-cut PR hasn't run, so the badge correctly
  stays at v0.14.0 until the Tier C release-cut PR.
- v0.14.3 closing paragraph: "follows slice 3b's merge" →
  "follows the release-cut PR's merge. Until that lands, this
  entry stays `## [0.14.3] — Unreleased`".

## What this PR does NOT do

- ❌ No README badge bump. CLAUDE.md golden rule #5 still
  applies — the release-cut PR (Tier C) hasn't run, so v0.14.3
  isn't a released version. Bumping now would replace one lie
  with another.
- ❌ No `Cargo.toml` / `tauri.conf.json` version bumps.
  These are part of the Tier C release cut (separate PR).
- ❌ No git tag, release notes, or installer build. Tier C.
- ❌ No code changes. Docs only.

## Tier

**A** — `CHANGELOG.md` + `ROADMAP.md`. PR auto-merge
eligible per CLAUDE.md Tier A rules.

## Verification

- [x] `node --test src/js/*.test.js` — 168/168 pass (includes
  the slice 3b `classifyNrc` tests added in PR #190)
- [x] `cargo test --lib --offline protocol::` — 15/15 pass
  (regression check; no code changes)
- [x] `npm run build` — `rc=0`, both MSI + NSIS bundles
  built (1m 52s)
- [x] ROADMAP cycle section header now reads "Shipped
  2026-07-30"
- [x] CHANGELOG `[0.14.3]` header preserved as
  "Unreleased" (correctly — release cut is separate)

## Cross-references

- PR #188 — v0.14.3 slice 4 (the original cycle-closeout
  PR that flagged slice 3b as the gating slice)
- PR #190 — v0.14.3 slice 3b (now merged; the close this
  PR's docs are catching up to)
- PR #192 — v0.14.1 + v0.14.2 CHANGELOG backfill (the
  previous round of version-surface housekeeping)
- CLAUDE.md golden rule #5 — version-surface sync (the rule
  this PR enforces retroactively for v0.14.3's slice 3b)

Co-authored-by: ohgeeceee <ohgeeceee@users.noreply.github.com>
github-actions Bot pushed a commit that referenced this pull request Jul 31, 2026
Two `this PR` placeholders survived the v0.14.3 cycle closeout
(PR #194) because they were inside multi-line cell text in
the v0.14.2 ROADMAP row and inside the v0.14.3 Tier A bullet
list in CHANGELOG. Both refer to PR #188 (v0.14.3 slice 4:
N62 / E70 harness-doc extension).

- ROADMAP.md line 528: v0.14.2 row notes column — "see PRs
  #185 (decoders), #186 (profile entries), and slice 4 (this
  PR, harness extension)" → "see PRs #185 (decoders), #186
  (profile entries), and slice 4 (PR #188, harness extension)".
- CHANGELOG.md line 200: v0.14.3 Tier A bullet — "**N62 / E70
  harness-doc extension** (this PR, slice 4, Tier A)" →
  "**N62 / E70 harness-doc extension** (PR #188, slice 4, Tier A)".

These are the only remaining "this PR" references in CHANGELOG
or ROADMAP (verified via `grep -nE '\(this PR[, ]|\bslice [0-9]+ \(this PR\b'`).
The fenced `## Template for next release` block in CHANGELOG
lines 952-972 is intentional — it's a documentation template
showing the format for future entries, not stale.

Tier A docs-only. No code changes.

Verification:
- [x] node --test src/js/*.test.js — 168/168 pass (no JS changes)
- [x] npm run build — rc=0, both bundles built

Diff: +2 / -2 (one substitution in each of 2 files).

Co-authored-by: ohgeeceee <ohgeeceee@users.noreply.github.com>
github-actions Bot pushed a commit that referenced this pull request Aug 2, 2026
…rate / runtime PIDs (#223)

Tier A, data only. v0.14.5 slice 1 of 3.

Mirrors the v0.14.2 N62 slice 1 (PR #175) and the v0.14.3 N62
slice 2 (PR #186) pattern: swap the unverified `local:10`
oil-temp placeholder for the standard SAE J1979 PID `0x5C`,
then add the three v0.14.3 PIDs (0x5E fuel rate L/h,
0x5F engine runtime, 0x62 fuel rate g/s). Each new entry
carries the `[needs verification, N5x/E9x bench]` marker
per the v0.14.3 N62 discipline.

Changes per file:

n52.toml:
  - oil placeholder: `local:10` (labelled `[UNVERIFIED
    placeholder]`) -> `obd:5C` (engine oil temperature,
    `byte - 40 °C`, decoder `temp_u8`)
  - 3 new entries: fuel_rate_lh (0x5E), engine_runtime
    (0x5F), fuel_rate_gs (0x62)
  - profile label: `[community, oil temp unverified]` ->
    `[community]` (the conservative-sourcing marker stays
    until a real-car report lifts it)
  - header block: BSD oil-condition sensor note (N52's known
    oil-temp quirk — DME reads oil condition via BSD, not
    KWP2000; the OBD-II `0x5C` swap is the surface the desktop
    app reads, but the harness-doc path reverts to `local:10`
    if the DME returns an NRC for `0x5C`)
  - 10 -> 13 [[profile.param]] entries

n54.toml:
  - same oil placeholder swap + 3 new entries
  - profile label: `[community, oil temp unverified]` ->
    `[community]`
  - header block: BSD note + charge-air / boost / HPFP /
    idle-voltage context (N54-specific; twin-turbo pulls more
    fuel at WOT than the NA N52 / N62 — fuel-rate ranges
    bumped to ~80-150 L/h and ~60-100 g/s)
  - 12 -> 15 [[profile.param]] entries

No Rust change. All four OBD-II PIDs reuse decoders that
shipped in v0.14.3 PR #185 (temp_u8, u16_fiftieths, u32_be,
u16_half). The v0.14.3 PR #187 per-PID NRC surface flags the
N52 / N54 `0x5C` BSD-not-supported failure mode in the UI;
the `remove_profile_pid` async command writes the updated
TOML behind a tauri-plugin-dialog confirmation per the
issue-#161 fix pattern.

Bench verification on the E9x is the gating step — see
`docs/validation/n5x-real-car.md` (v0.14.5 slice 2).

Author note: commit authored with
ohgeeceee@users.noreply.github.com to bypass GH007
(private-email push block). Content unchanged.

Co-authored-by: ohgeeceee <ohgeeceee@users.noreply.github.com>
github-actions Bot pushed a commit that referenced this pull request Aug 2, 2026
Tier A, docs only. v0.14.5 slice 2 of 3. Closes the cycle.

Mirrors the v0.14.2 N62 harness doc
(docs/validation/n62-real-car.md, PR #178 + PR #188) and
adapts it for the E9x N52 / N54 family that v0.14.5 slice
1 (PR #223) just enriched. The doc is the report-back
loop an E9x owner runs on a real car to lift the
`[needs verification, N5x/E9x bench]` markers PR #223
placed on the four new OBD-II PIDs (`0x5C` oil temp,
`0x5E` fuel rate L/h, `0x5F` engine runtime,
`0x62` fuel rate g/s).

Five-section shape (mirrors the N62 harness doc):

  1. What this is — the per-PID list, N52 BSD note,
     N54 charge-air / boost / HPFP context.
  2. Step 1 — wire-up — K+DCAN cable on E9x (pin
     6+14 D-CAN, pin 7 K-line fallback).
  3. Step 2 — cold readings — 13 N52 PIDs + 15 N54
     PIDs. Critical rows: oil temp (N52 BSD
     failure mode flagged), fuel rate at idle/WOT.
  4. Step 3 — running readings — 13 N52 PIDs +
     15 N54 PIDs. N54 ranges bumped for
     twin-turbo (WOT ~80-150 L/h vs N52's
     ~50-90 L/h).
  5. Step 4 — report template — markdown block
     with chassis + firmware + cable + profile
     + per-state readings.
  6. Step 5 — what we do with the report —
     passing report removes the verification
     markers; failing report reverts per-PID.
     **The N52-specific BSD-not-supported failure
     mode is documented explicitly:** if the N52
     DME returns an NRC for `0x5C` on a given
     firmware, the protocol reverts the oil
     entry to `local:10` placeholder via the
     v0.14.3 PR #187 per-PID NRC surface +
     `remove_profile_pid` async Tauri command.

The N52 BSD oil-condition sensor note is the
load-bearing difference from the N62 harness doc.
The N54-specific sections (charge-air / boost /
HPFP rail / WOT fuel-rate ranges) are the
N54-specific additions.

No transport/**, protocol/**, commands.rs, or
frontend changes. No new crates. No new BMW hex
descriptions. No git tag v0.14.5 (Tier C release
cut is the next step after this PR lands).

Cross-references: v0.14.5 plan (PR #222), v0.14.5
slice 1 (PR #223), N62 cycle predecessors (PRs
#175, #185, #186, #187, #188, #190, #208),
docs/DECODE_FUNCTIONS.md § 3/10/11/12.

Author note: commit authored with
ohgeeceee@users.noreply.github.com to bypass GH007
(private-email push block). Content unchanged.

Co-authored-by: ohgeeceee <ohgeeceee@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant