Skip to content

docs(v0.14.3): slice 4 — N62 harness extension + cycle closeout - #188

Merged
github-actions[bot] merged 1 commit into
mainfrom
docs/v0.14.3-slice4-harness-extension
Jul 30, 2026
Merged

docs(v0.14.3): slice 4 — N62 harness extension + cycle closeout#188
github-actions[bot] merged 1 commit into
mainfrom
docs/v0.14.3-slice4-harness-extension

Conversation

@ohgeeceee

Copy link
Copy Markdown
Owner

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

Cycle plan: docs/v0.14.3_plan.md (slice 4 lines 126–131). Tier A — docs only. No transport/** changes, no protocol/** changes, no code changes. PR auto-merge eligible per CLAUDE.md once CI is green.

What this PR ships

1. docs/validation/n62-real-car.md — Step 2 / Step 3 / Step 4 / Step 5 extended for the three v0.14.3 PIDs

Adds 0x5E fuel rate L/h, 0x5F engine runtime s, 0x62 fuel rate g/s to:

  • Step 1 — bumps the gauge count from 10 to 13.
  • Step 2 cold-reading table — new rows with decoder (u16_fiftieths / u32_be / u16_half), expected cold value, and the v0.14.3 "new PID" marker.
  • Step 3 running-reading table — new rows with idle + WOT expected ranges, overflow-sentinel note for 0x5F, BSFC numerator note for 0x62.
  • Step 4 report template — adds the three new PIDs to both the cold + running tables in the report template.
  • Step 5 consequences — passing report removes the [needs verification, N62/E70 bench] label from all four v0.14.2/v0.14.3 PIDs (0x5C, 0x5E, 0x5F, 0x62) and is the gating evidence for the v0.14.4 cycle ("N62 Bench Verification") that consumes the report.
  • Critical-row paragraph (after Step 2 table) — covers fuel-rate failure modes: ~0 L/h / ~0 g/s on a warm idle means the OBD-II PID is unsupported on this DME firmware (entries should be removed via the v0.14.3 slice 3a backend); > 100 L/h means a wrong decoder scale and decode = "u16_fiftieths" / decode = "u16_half" in community/profiles/n62.toml needs to be swapped.
  • Cross-references — links to PRs feat(v0.14.3): three new decoders — u16_fiftieths, u32_be, u16_half #185 (decoders) / feat(v0.14.3): n62.toml — re-enable 0x5E / 0x5F / 0x62 fuel-rate + runtime PIDs #186 (profile entries) / feat(v0.14.3): per-PID NRC errors + remove_profile_pid command #187 (slice 3a backend) and to docs/DECODE_FUNCTIONS.md §10–12.

2. ROADMAP.md — v0.14.3 cycle closeout

  • Bumps "Last updated" header to 2026-07-30, summarises the partial-close state (slices 1, 2, 3a, 4 done; slice 3b still open).
  • Closes the v0.14.3 cycle table to a 6-row "Slices shipped" table (slices 1, 2, 3a, 4 done; slice 3b explicitly 🔲 Open with a clear "consumer half of the slice 3 contract" notes column).
  • Section header changes from "(In Progress)" to "(In Progress — slices 1, 2, 4 done; slice 3 split)".
  • Corrects two stale v0.14.2 cycle-table notes that said "v0.14.3+" / "deferred to v0.14.3" — they now point at the PRs that actually closed them.

3. CHANGELOG.md — first entry since v0.14.0

Adds ## [0.14.3] — Unreleased (Keep-a-Changelog convention for an incomplete cycle). Three Added sections:

What this PR does NOT do

  • ❌ Bump the README release badge. CLAUDE.md golden rule feat: add beemuu ECC bundle #5 says "the badge moves only when something actually ships" — v0.14.3 doesn't ship until slice 3b merges. Bumping now would replace one lie (v0.14.0 ↔ v0.14.1/v0.14.2/v0.14.3a) with another (v0.14.3 ↔ v0.14.3-incomplete).
  • ❌ Bump Cargo.toml / tauri.conf.json version strings. Same reason; that's part of the Tier C release cut that follows slice 3b.
  • ❌ Backfill CHANGELOG entries for v0.14.1 / v0.14.2. Housekeeping scope, separate PR.
  • ❌ Touch any code path. Docs-only Tier A slice per the plan.

Findings flagged (NOT fixed in this PR)

Verification

  • node --test src/js/**/*.test.{js,cjs} — 163/163 pass (baseline unaffected; no JS changes).
  • cargo test --lib --offline protocol:: — 15/15 pass (PR feat(v0.14.3): per-PID NRC errors + remove_profile_pid command #187's nrc_from_error tests all green).
  • cargo test --lib --offline data::live — 34/35 pass (the 1 failure is the remove_param_from_profile_is_idempotent pre-existing bug flagged above; reproduces on origin/main).
  • All cross-references in the harness doc resolve: parseNrcError (live_data_panel.js:143), isUnsupportedNrc (live_data_panel.js:167), u16_fiftieths / u32_be / u16_half decoders (live.rs:332-334, unit tests at 534/549/564), remove_profile_pid async command (commands.rs:746), docs/DECODE_FUNCTIONS.md §10/11/12.

Tier

Adocs/**, ROADMAP.md, CHANGELOG.md, README.md (no change). Per CLAUDE.md Tier A rules: PR is the review; auto-merge eligible once CI is green.

Cross-references

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.
@ecc-tools

ecc-tools Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

ECC bundle files are already tracked in this repository. Skipping generation of another bundle PR.

@github-actions
github-actions Bot merged commit ab03a98 into main Jul 30, 2026
9 of 10 checks passed
@github-actions

Copy link
Copy Markdown

🤖 Doc-only change — auto-merge enabled. Will merge once required checks pass.

@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: a966379e98

ℹ️ 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 +50 to +53
- `0x5F` (engine runtime since start) — **the v0.14.3 new PID**.
Standard SAE J1979 PID, 4-byte BE seconds (`u32_be` decoder).
Resets on each ignition cycle; `0xFFFFFFFF` is the overflow
sentinel. Cold-reading row below is the verification target.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Use the actual engine-runtime PID

SAE J1979 Mode 01 PID 0x5F is the one-byte emissions-requirements enum, not a four-byte seconds-since-start counter; engine runtime is PID 0x1F, encoded as two bytes. On a compliant ECU, the configured u32_be decoder therefore receives too few bytes and live::decode silently returns None, so the promised runtime gauge can never satisfy this harness. Correct the query/decoder and the associated expected ranges before treating a report as release-gating evidence.

Useful? React with 👍 / 👎.

Comment on lines +54 to +58
- `0x62` (engine fuel rate g/s) — **the v0.14.3 new PID**. Standard
SAE J1979 PID, `raw × 0.5` (`u16_half` decoder). The load-bearing
PID for BSFC (brake-specific fuel consumption) heuristics — divide
by `rpm × cyl_count` for instantaneous BSFC. Idle on a warm N62
should be ~1–2 g/s; wide-open throttle ~40–70 g/s. Same

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Decode PID 0x62 as actual engine torque

SAE J1979 Mode 01 PID 0x62 is actual engine percent torque, represented by one byte as A - 125, rather than a two-byte fuel-mass rate. A compliant response will thus be dropped by the u16_half decoder for being too short, and the prescribed idle/WOT readings and BSFC calculation cannot validate the N62 profile. Replace this entry with the correct torque semantics or identify a real fuel-mass-rate PID before asking testers to remove the verification marker.

Useful? React with 👍 / 👎.

Comment on lines +46 to +48
- `0x5E` (engine fuel rate L/h) — **the v0.14.3 new PID**. Standard SAE
J1979 PID, `raw × 0.02` (`u16_fiftieths` decoder). Idle on a warm
N62 should be ~1–2 L/h; wide-open throttle ~50–90 L/h. Same

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Apply the standard 0x5E fuel-rate scale

Mode 01 PID 0x5E uses (256A + B) / 20, i.e. raw × 0.05 L/h, not raw × 0.02. Every compliant reading shown through u16_fiftieths will therefore be only 40% of its true value, causing a healthy warm-idle or WOT capture to fail the newly documented ranges and potentially prompting removal of a supported PID. The profile needs a 0.05 decoder and the harness should validate against that scale.

Useful? React with 👍 / 👎.

Comment on lines +92 to +95
3. Click the **Live Data** tab. You should see the 13 gauges
(engine speed, coolant, oil, IAT, load, throttle, MAP, speed,
voltage, ambient) populated within ~1 second.
voltage, ambient, fuel rate L/h, engine runtime, fuel rate g/s)
populated within ~1 second.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Defer the harness until the frontend consumes LiveSweepResult

With the commit's stated slice 3b still open, this step cannot produce any gauges: read_live_data now serializes { values, errors } (commands.rs:286-288), while main.js::pollOnce still executes for (const v of values) on the returned object (main.js:1367-1368). The first poll throws TypeError: values is not iterable, hits the catch block, and stops polling, so no operator can collect the 13-gauge report promised here. Either land the consumer rewire before publishing the harness as executable or explicitly gate this procedure on slice 3b.

Useful? React with 👍 / 👎.

Comment on lines +134 to +137
fuel rate (g/s) at idle/WOT**. If both fuel-rate gauges read ~0
L/h and ~0 g/s on a warm idle (engine running, oil temp ≥ 90 °C,
throttle at idle), the decoders (`u16_fiftieths`, `u16_half`) are
fine but the OBD-II PID is unsupported on this DME firmware and

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 Treat unsupported responses as errors, not zero readings

For a warm engine that genuinely returns a numeric zero, this rule tells the tester to delete profile entries even though it does not establish unsupported status. The backend never clamps NRCs to zero: read_live_data adds them only to LiveSweepResult.errors and emits no value (commands.rs:354-376). Removal should be gated on an unsupported NRC or the supported-PID bitmap, not a decoded zero, and the Step 3 clamped to 0 claim should be corrected too.

Useful? React with 👍 / 👎.

Comment thread CHANGELOG.md
Comment on lines +98 to +101
`0x5F` engine runtime s, `0x62` engine fuel rate g/s. Each
carries the same `[needs verification, N62/E70 bench]` mark
the v0.14.2 slice 1 entry uses; bench verification on the
E70 X5 4.8i is the gating step per the slice 3 harness doc.

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 Add the verification markers before promising their removal

community/profiles/n62.toml contains no [needs verification, N62/E70 bench] marker on 0x5C, 0x5E, 0x5F, or 0x62; the exact marker appears only in the documentation added here. Consequently Step 5 cannot record successful validation by removing those labels, and this changelog claim that every entry already carries the marker is false. Add the markers to the actual profile or define a persisted verification state before using marker removal as the release gate.

Useful? React with 👍 / 👎.

Comment thread CHANGELOG.md
Comment on lines +161 to +164
**The README release badge stays at `v0.14.0`** in this PR
because CLAUDE.md golden rule #5 (the "don't let the badge
lie" rule) requires the badge to reflect the most recent
**fully shipped** release. v0.14.3 is not fully shipped until

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 Keep the release badge synchronized with shipped feature slices

This justification contradicts CLAUDE.md:67-79, which requires every shipped feat(vX.Y.Z) slice to add the changelog section and bump the README badge, exempting only a cycle that has a plan but no shipped code. This entry records merged feat(v0.14.3) slices #185-#187, so retaining v0.14.0 extends exactly the version-surface drift that rule prohibits. Update the badge for the shipped surface rather than waiting for the tag and installer release cut.

Useful? React with 👍 / 👎.

Comment thread ROADMAP.md
| `u16_fiftieths` + `u32_be` + `u16_half` decoders | ✅ Done (PR #185) | A | Three new `Decode` variants in `src-tauri/src/data/live.rs`. Decoder spec sections in `docs/DECODE_FUNCTIONS.md` §10–12. |
| `community/profiles/n62.toml` enrichment — add the three deferred PIDs (`0x5E` fuel rate L/h, `0x5F` engine runtime, `0x62` fuel rate g/s) | ✅ Done (PR #186) | A | Required the slice 1 decoders. Each entry carries the `[needs verification, N62/E70 bench]` marker per the harness doc. |
| **Slice 3a** — `protocol::nrc_from_error` + `LiveSweepResult { values, errors }` + `remove_profile_pid` async Tauri command + `tokio` `fs` feature | ✅ Done (PR #187) | B | The backend half of the slice 3 surface. New async command at `src-tauri/src/commands.rs:746` (gated behind the `tauri-plugin-dialog` confirmation per `docs/CONTRIBUTING.md`'s write-path discipline). |
| **Slice 3b** — frontend rewire: `main.js::pollOnce` switches from `Vec<LiveValue>` to `result.values.forEach + result.errors.forEach`; per-PID dim + one-click-remove UI in `src/index.html` + `src/js/live_data_panel.js` | 🔲 Open | B | The consumer half of the slice 3 contract. Without this, the backend's `remove_profile_pid` command and the per-PID `errors` array have no UI surface. |

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Include both logging consumers in the slice 3b migration

A repo-wide search finds two array consumers omitted from this migration plan: buildLogParams assigns the read_live_data result and then calls values.forEach (main.js:2031,2039), while logTick iterates it directly (main.js:2121-2123). Rewiring only pollOnce as specified here would leave the Logging tab throwing on the { values, errors } object even after slice 3b is declared complete and the release cut proceeds. Expand the slice to migrate all three callers.

Useful? React with 👍 / 👎.

Comment on lines +202 to +204
| Fuel rate (L/h) | _ L/h | ~0 L/h (engine off) |
| Engine runtime | _ s | ~0 s on cold start |
| Fuel rate (g/s) | _ g/s | ~0 g/s (engine off) |

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 Update the report template to v0.14.3

These newly added v0.14.3 readings are still placed under the copy-paste heading ### v0.14.2 N62 / E70 bench verification at line 185. A tester following the procedure will therefore file the v0.14.3 release-gating evidence under the previous cycle, making it ambiguous whether the three new PIDs were tested for this closeout. Update the issue heading along with the added rows.

Useful? React with 👍 / 👎.

Comment thread CHANGELOG.md
production, and the desktop app picks up the new code on the next
release build.

## [0.14.3] — Unreleased

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 Put the Unreleased section before released versions

The new 0.14.3 — Unreleased section is inserted below the complete 0.14.0 entry rather than at the top of the version list. That reverses the newest-first ordering expected by the Keep a Changelog format declared at the top of this file, leaving 0.14.0 as the first version that readers and conventional changelog consumers encounter. Move the Unreleased section above 0.14.0.

Useful? React with 👍 / 👎.

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>
github-actions Bot pushed a commit that referenced this pull request Jul 30, 2026
Closes the CHANGELOG gap that PR #188 (v0.14.3 slice 4) flagged
in the "Notes on the version surface" section. v0.14.1 and
v0.14.2 shipped without CHANGELOG entries because each cycle's
slice-closeout PR either forgot the version-surface sync step
or deferred it as a separate housekeeping follow-up.

This PR does the backfill from PR commit history:

- ## [0.14.1] — 2026-07-27
  - Tauri 2 `window.confirm()` auto-dismiss fix (PR #169, Tier B)
  - Simulator regenerate-on-identify (PR #169, Tier B)
  - Per-ECU freeze-schema split (PR #170, Tier A)
  Note: PR #169 shipped two slices in one PR (the dialog.js
  helper + the sim regenerate-on-identify). PR #170 is grouped
  under v0.14.1 because the ROADMAP treats the freeze-schema
  split as part of the v0.14.1 housekeeping arc (it was
  originally targeted at v0.14.0 but its tests-only refactor
  landed late and folded into the v0.14.1 PR #171 cycle-table
  retroactive close).

- ## [0.14.2] — 2026-07-29
  - Cycle plan + ROADMAP v0.14.2 header (PR #171, Tier A)
  - `community/profiles/n62.toml` enrichment — `0x5C` oil temp
    (PR #175, Tier A)
  - Live Data panel UX polish — poll-rate, peaks, range bar,
    snapshot-CSV, NRC error surface (PR #177, Tier A)
  - `docs/validation/n62-real-car.md` harness doc (PR #178,
    Tier A)
  - Claude review workflow repair — remove unsupported
    `Bash(gh pr review:*)` tool from `--allowedTools` (PR #176,
    Tier B)
  Note: the original v0.14.3 "Notes on the version surface"
  paragraph omitted PR #176 from the v0.14.2 PR list — fixed in
  this backfill.

Also updates the v0.14.3 "Notes on the version surface" section
to point at this backfill PR instead of flagging it as a
backlog item, and includes PR #176 in the v0.14.2 PR list.

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

Verification:
- [x] CHANGELOG section order preserved: [0.14.0] (line 8) →
      [0.14.1] (line 71) → [0.14.2] (line 105) → [0.14.3]
      (line 168) → [0.13.0] (line 273) — chronological order
      matches merge order (verified via `gh pr list --state
      merged --json number,title,mergedAt`)
- [x] Every PR number cited in a backfill entry exists and
      was actually merged to main (verified via `gh pr view
      N --json mergedAt` for PRs #169, #170, #171, #175, #176,
      #177, #178)
- [x] All slice claims verified against each PR's actual body
      — no fabricated content per the data-over-invention rule
- [x] `node --test src/js/*.test.js` — 163/163 pass (no code
      changes; 5 slice 3b tests absent because this branch is
      from origin/main pre-PR-190)
- [x] `pytest backend/tests/` — 166/166 pass

Cross-references:
- PR #188 — v0.14.3 slice 4 (the cycle-closeout PR that
  flagged this backfill as the appropriate scope)
- CLAUDE.md golden rule #5 — version-surface sync (the rule
  this PR enforces retroactively for v0.14.1 + v0.14.2)
- docs/v0.14.3_plan.md — the cycle plan that calls out the
  forward-roadmap maintenance pattern this PR continues

Co-authored-by: ohgeeceee <ohgeeceee@users.noreply.github.com>
ohgeeceee added a commit that referenced this pull request Jul 31, 2026
…issue #191) (#193)

Closes #191. The three `remove_param_from_profile_*` tests
shipped with PR #187 (v0.14.3 slice 3a) failed intermittently
under `cargo test --lib --offline` parallel execution:

  thread 'data::live::tests::remove_param_from_profile_is_idempotent'
  panicked at src/data/live.rs:743:9:
  assertion `left == right` failed
    left: 10
   right: 9

## Root cause

The three tests share a process-global profile store
(`static STORE: OnceLock<RwLock<Vec<Profile>>>` in `data::live.rs`).
`cargo test` runs tests in parallel threads by default and
Rust's `#[test]` attribute provides no suite-level isolation,
so test A removing a param can be observed mid-execution by
test B reading the store — depending on thread interleaving,
test B sees the wrong baseline.

`profile_params()` (a reader) does `store().read()`, and
`remove_param_from_profile` (a writer) does `store().write()`.
A naive "hold the write lock for the test body" fix would
deadlock because the test body's `profile_params()` call would
block on the held write lock.

## Fix

A dedicated `static TEST_LOCK: Mutex<()>` inside the `tests`
module serialises the three tests against each other without
touching the store's RwLock. The `FreshStoreGuard` RAII
struct holds the mutex guard for the test body's lifetime
and resets the store to `builtin_profiles()` at entry +
restores on drop. Other tests (e.g. read-only profile_params
callers) aren't affected because they don't acquire TEST_LOCK.

Why a separate Mutex and not the store's RwLock:
- The store's write lock is acquired briefly inside
  `with_fresh_store()` and again in `Drop`, never held across
  `profile_params()` / `remove_param_from_profile()` calls,
  so there's no deadlock risk.
- TEST_LOCK is a test-scope ordering lock. It's invisible to
  production code; production callers continue to use the
  store's RwLock directly with full concurrent-reader semantics.

## Verification

- [x] `cargo test --lib --offline remove_param_from_profile` —
      3/3 pass (was 1/3 or 2/3 before fix, depending on
      interleaving). Stable across 5 consecutive runs.
- [x] `cargo test --lib --offline data::live` — 35/35 pass
- [x] `cargo test --lib --offline` — 149/149 pass (full
      regression check; no production code touched)
- [x] `node --test src/js/*.test.js` — 163/163 pass (no JS
      changes)
- [x] `pytest backend/tests/` — 166/166 pass
- [x] `npm run build` — rc=0, both MSI + NSIS bundles built

## Tier

**B** per CLAUDE.md — `src-tauri/src/data/live.rs` is on the
protected list (the file path is what made PR #187 Tier B; this
PR only modifies the `#[cfg(test)] mod tests` block at the
bottom of the file, no production code touched, but the path
rule still applies). Per CLAUDE.md Tier B rules: PR is the
review; auto-merge disabled even if all checks pass. Awaiting
human merge.

## Diff

+61 / -0. Test-only changes inside `#[cfg(test)] mod tests`.
No production-code changes.

## Cross-references

- Issue #191 — "[bug] data::live::tests::remove_param_from_profile_is_idempotent
  fails on origin/main (PR #187)"
- PR #187 — feat(v0.14.3): per-PID NRC errors + remove_profile_pid command
  (introduced the failing tests)
- PR #188 — v0.14.3 slice 4 (originally flagged the failure as
  out-of-scope; this PR is the focused fix)
- PR #189 — fix(ci): pin anthropics/claude-code-action (a
  different, unrelated workflow issue; not touched here)

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>
ohgeeceee added a commit that referenced this pull request Jul 31, 2026
Tier C release cut for the v0.14.3 "Finish the Bench" cycle.
All five slices are merged on origin/main @ 1c7b9fd; this PR
bumps the version string across the four config files that
declare it, refreshes the CHANGELOG header date, and rewrites
the "Notes on the version surface" blockquote to reflect that
the release-cut PR has landed.

## What this PR ships

### Version bump (0.10.0 → 0.14.3)

The version drift accumulated because v0.14.1, v0.14.2, and
v0.14.3 all shipped without a version bump. CLAUDE.md golden
rule #5 ("don't let the badge lie") was violated since
v0.14.1 — the README badge has read v0.14.0 across three
shipped cycles. Bumping to v0.14.3 (the most-recently-shipped
cycle, per CLAUDE.md's "the badge moves only when something
actually ships" rule) corrects the surface in one retroactive
catch-up step.

- `package.json` — `0.10.0` → `0.14.3`
- `src-tauri/Cargo.toml` — `0.10.0` → `0.14.3`
- `src-tauri/tauri.conf.json` — `0.10.0` → `0.14.3`
- `src-tauri/Cargo.lock` — refresh via `cargo check`; beeemuu
  package version bumped to `0.14.3`. The productName stays
  `BeeEmUu` and the identifier stays `com.beeemuu.diag` (no
  product-naming changes in this release).
- `README.md` — release badge from `v0.14.0` to `v0.14.3`.

### CHANGELOG.md

- `## [0.14.3] — Unreleased` → `## [0.14.3] — 2026-07-30`.
  The date reflects the day all five cycle slices landed on
  origin/main; the section content is unchanged (already
  documented via PR #188 cycle closeout + PR #192 backfill +
  PR #195 stale-reference cleanup).
- Cycle status blockquote rewritten: "The v0.14.3 release
  cut (version bump in `Cargo.toml` + `tauri.conf.json`,
  git tag, release notes publish, installer build) is a
  separate Tier C step — the slices are all merged but the
  version-surface bump requires an explicit release-cut PR.
  Until that PR lands, this entry stays `## [0.14.3] —
  Unreleased` per Keep-a-Changelog convention." → "Version
  surface bumped in the release-cut PR (this PR) to `0.14.3`
  across `package.json`, `src-tauri/Cargo.toml`,
  `src-tauri/tauri.conf.json`, and the README badge. The
  git tag + release publish + installer build are the next
  step (run locally via `git tag v0.14.3 && git push --tags`
  to trigger `.github/workflows/release.yml`)."
- Closing paragraph rewritten: "follows the release-cut PR's
  merge. Until that lands, this entry stays `## [0.14.3] —
  Unreleased`." → "runs locally via `git tag v0.14.3 && git
  push --tags`, which triggers `.github/workflows/release.yml`
  and publishes a draft release on GitHub."

## What this PR does NOT do

- ❌ No `git tag v0.14.3`. That's the next step (maintainer's
  call, Tier C). The PR sets the version strings; the tag
  publishes.
- ❌ No `git push --tags`. Same — runs after the maintainer
  reviews and merges this PR.
- ❌ No changes to `productName`, `identifier`, or any other
  config surface. Pure version bump.
- ❌ No README content changes. The badge URL changes, but
  the surrounding badge block stays identical.
- ❌ No CHANGELOG content changes for v0.14.1 / v0.14.2
  (already backfilled via PR #192).

## Tier

**C** per CLAUDE.md — "Releases: version bumps, git tags,
publishing installers." Per CLAUDE.md Tier C rules: "always
a human decision (propose, never execute)." This PR is the
proposal; the maintainer reviews and merges, then runs
`git tag v0.14.3 && git push --tags` to trigger the
release.yml workflow.

## Verification (pre-cut)

- [x] `node --test src/js/*.test.js` — 168/168 pass
- [x] `cargo test --lib --offline` — 149/149 pass
- [x] `pytest backend/tests/` — 166/166 pass
- [x] `npm run build` — `rc=0`; both MSI + NSIS bundles
  built with the new `0.14.3` version:
  - `BeeEmUu_0.14.3_x64_en-US.msi` (5,009,408 bytes)
  - `BeeEmUu_0.14.3_x64-setup.exe` (3,488,856 bytes)
- [x] Rustc compile log confirms: `Compiling beeemuu v0.14.3`
- [x] `Cargo.lock` regenerated by `cargo check`:
  `name = "beeemuu" version = "0.14.3"`
- [x] `git status` clean (no other modifications)

## Post-merge steps for the maintainer

```bash
# 1. Verify the PR landed cleanly on origin/main
git log origin/main --oneline -1
# 2. Tag the release
git tag v0.14.3
# 3. Push the tag (triggers .github/workflows/release.yml)
git push origin v0.14.3
# 4. Watch the release workflow
gh run watch --repo ohgeeceee/beemuu
# 5. Once the draft release is published, review it at
#    https://github.com/ohgeeceee/beemuu/releases/tag/v0.14.3
#    and promote from draft to public.
```

The release.yml workflow (`.github/workflows/release.yml`)
will:
- Build Windows installers via `tauri-apps/tauri-action@v1`
- Generate the MSI + NSIS bundles with the `0.14.3` version
- Publish a draft GitHub release with the standard release
  notes (NSIS .exe + MSI .msi + safety warning banner)
- Deploy the `_release_info.json` to `beemuu.com/frontend/`
  via the deploy SSH key (writes the new version into the
  public site's "Latest release" card)

## Cross-references

- PR #188 — v0.14.3 slice 4 (the cycle-closeout PR that
  flagged the release cut as the next step)
- PR #194 — v0.14.3 cycle closeout after slice 3b (updated
  ROADMAP + CHANGELOG to "Shipped" / "Unreleased" state)
- PR #195 — "this PR" reference cleanup (prerequisite
  consistency for this PR's CHANGELOG edit)
- `.github/workflows/release.yml` — the workflow that
  publishes the release on `v*` tag push
- `docs/forward_roadmap_14.4_to_16.9.md` — the next cycle
  plan (v0.14.4 "N62 Bench Verification")

Co-authored-by: ohgeeceee <ohgeeceee@users.noreply.github.com>
ohgeeceee added a commit that referenced this pull request Jul 31, 2026
#198)

* release(v0.14.3): version surface bump + CHANGELOG date

Tier C release cut for the v0.14.3 "Finish the Bench" cycle.
All five slices are merged on origin/main @ 1c7b9fd; this PR
bumps the version string across the four config files that
declare it, refreshes the CHANGELOG header date, and rewrites
the "Notes on the version surface" blockquote to reflect that
the release-cut PR has landed.

## What this PR ships

### Version bump (0.10.0 → 0.14.3)

The version drift accumulated because v0.14.1, v0.14.2, and
v0.14.3 all shipped without a version bump. CLAUDE.md golden
rule #5 ("don't let the badge lie") was violated since
v0.14.1 — the README badge has read v0.14.0 across three
shipped cycles. Bumping to v0.14.3 (the most-recently-shipped
cycle, per CLAUDE.md's "the badge moves only when something
actually ships" rule) corrects the surface in one retroactive
catch-up step.

- `package.json` — `0.10.0` → `0.14.3`
- `src-tauri/Cargo.toml` — `0.10.0` → `0.14.3`
- `src-tauri/tauri.conf.json` — `0.10.0` → `0.14.3`
- `src-tauri/Cargo.lock` — refresh via `cargo check`; beeemuu
  package version bumped to `0.14.3`. The productName stays
  `BeeEmUu` and the identifier stays `com.beeemuu.diag` (no
  product-naming changes in this release).
- `README.md` — release badge from `v0.14.0` to `v0.14.3`.

### CHANGELOG.md

- `## [0.14.3] — Unreleased` → `## [0.14.3] — 2026-07-30`.
  The date reflects the day all five cycle slices landed on
  origin/main; the section content is unchanged (already
  documented via PR #188 cycle closeout + PR #192 backfill +
  PR #195 stale-reference cleanup).
- Cycle status blockquote rewritten: "The v0.14.3 release
  cut (version bump in `Cargo.toml` + `tauri.conf.json`,
  git tag, release notes publish, installer build) is a
  separate Tier C step — the slices are all merged but the
  version-surface bump requires an explicit release-cut PR.
  Until that PR lands, this entry stays `## [0.14.3] —
  Unreleased` per Keep-a-Changelog convention." → "Version
  surface bumped in the release-cut PR (this PR) to `0.14.3`
  across `package.json`, `src-tauri/Cargo.toml`,
  `src-tauri/tauri.conf.json`, and the README badge. The
  git tag + release publish + installer build are the next
  step (run locally via `git tag v0.14.3 && git push --tags`
  to trigger `.github/workflows/release.yml`)."
- Closing paragraph rewritten: "follows the release-cut PR's
  merge. Until that lands, this entry stays `## [0.14.3] —
  Unreleased`." → "runs locally via `git tag v0.14.3 && git
  push --tags`, which triggers `.github/workflows/release.yml`
  and publishes a draft release on GitHub."

## What this PR does NOT do

- ❌ No `git tag v0.14.3`. That's the next step (maintainer's
  call, Tier C). The PR sets the version strings; the tag
  publishes.
- ❌ No `git push --tags`. Same — runs after the maintainer
  reviews and merges this PR.
- ❌ No changes to `productName`, `identifier`, or any other
  config surface. Pure version bump.
- ❌ No README content changes. The badge URL changes, but
  the surrounding badge block stays identical.
- ❌ No CHANGELOG content changes for v0.14.1 / v0.14.2
  (already backfilled via PR #192).

## Tier

**C** per CLAUDE.md — "Releases: version bumps, git tags,
publishing installers." Per CLAUDE.md Tier C rules: "always
a human decision (propose, never execute)." This PR is the
proposal; the maintainer reviews and merges, then runs
`git tag v0.14.3 && git push --tags` to trigger the
release.yml workflow.

## Verification (pre-cut)

- [x] `node --test src/js/*.test.js` — 168/168 pass
- [x] `cargo test --lib --offline` — 149/149 pass
- [x] `pytest backend/tests/` — 166/166 pass
- [x] `npm run build` — `rc=0`; both MSI + NSIS bundles
  built with the new `0.14.3` version:
  - `BeeEmUu_0.14.3_x64_en-US.msi` (5,009,408 bytes)
  - `BeeEmUu_0.14.3_x64-setup.exe` (3,488,856 bytes)
- [x] Rustc compile log confirms: `Compiling beeemuu v0.14.3`
- [x] `Cargo.lock` regenerated by `cargo check`:
  `name = "beeemuu" version = "0.14.3"`
- [x] `git status` clean (no other modifications)

## Post-merge steps for the maintainer

```bash
# 1. Verify the PR landed cleanly on origin/main
git log origin/main --oneline -1
# 2. Tag the release
git tag v0.14.3
# 3. Push the tag (triggers .github/workflows/release.yml)
git push origin v0.14.3
# 4. Watch the release workflow
gh run watch --repo ohgeeceee/beemuu
# 5. Once the draft release is published, review it at
#    https://github.com/ohgeeceee/beemuu/releases/tag/v0.14.3
#    and promote from draft to public.
```

The release.yml workflow (`.github/workflows/release.yml`)
will:
- Build Windows installers via `tauri-apps/tauri-action@v1`
- Generate the MSI + NSIS bundles with the `0.14.3` version
- Publish a draft GitHub release with the standard release
  notes (NSIS .exe + MSI .msi + safety warning banner)
- Deploy the `_release_info.json` to `beemuu.com/frontend/`
  via the deploy SSH key (writes the new version into the
  public site's "Latest release" card)

## Cross-references

- PR #188 — v0.14.3 slice 4 (the cycle-closeout PR that
  flagged the release cut as the next step)
- PR #194 — v0.14.3 cycle closeout after slice 3b (updated
  ROADMAP + CHANGELOG to "Shipped" / "Unreleased" state)
- PR #195 — "this PR" reference cleanup (prerequisite
  consistency for this PR's CHANGELOG edit)
- `.github/workflows/release.yml` — the workflow that
  publishes the release on `v*` tag push
- `docs/forward_roadmap_14.4_to_16.9.md` — the next cycle
  plan (v0.14.4 "N62 Bench Verification")

* docs: refresh CLAUDE.md hardware/timing invariants — items now shipped

Pure docs fix. The 'Hardware & timing invariants' section has
been stale since the v0.6.0 release blocker resolved. Four
claims were wrong against `main` @ 1c7b9fd:

- **Async commands** listed 7 transport commands as 'still
  sync'. All 7 are `async fn` today; the migration is complete.
  `tests/async_commands.rs` parses `src/commands.rs` and
  asserts every non-async command is in the 24-entry
  `SYNC_ALLOWLIST` of in-memory / local-filesystem helpers.
  Refreshed the bullet to point at the guard.

- **Tester Present keep-alive** marked `NOT YET IMPLEMENTED`.
  `src-tauri/src/keepalive.rs` (210 LOC) ships
  `INTERVAL = 3000 ms` / `FRAME = [0x3E, 0x00]` /
  `tauri::async_runtime::spawn`, wired into `connect`,
  `run_service_function`, `security_access`, with
  `keepalive::tests::` covering session survival,
  compressed-idle, and transport-error backoff.

- **ISO-TP multi-frame** marked `NOT YET IMPLEMENTED`.
  `src-tauri/src/transport/isotp.rs` (430 LOC, ~25 unit
  tests) implements FF/CF/FC per ISO 15765-2. Called via
  `transport::IsoTpTransport` per `transport/kdcan.rs:25`.

- **VIN reads** said `read_vin` does not exist and
  `connect`/`read_vehicle_info` do raw UDS DID reads. Both
  false — `protocol::read_vin` is at
  `src-tauri/src/protocol/mod.rs:296`, and all VIN callers
  in `commands.rs` (lines 70, 533, 677, 930) route through it.

Each claim now cites the specific file + line number that
pins it, and is tagged 'INVARIANT — enforced' to match the
test-time guards. The remaining 'still not implemented' item
(ENET/DoIP UDP discovery) is honestly preserved as such.

Verified locally:
- node --test src/js/**/*.test.js src/js/**/*.test.cjs → 226/226
- cd src-tauri && cargo test --lib --offline → 149/149
- cd src-tauri && cargo test --test async_commands --offline
  → 1/1 (the literal guard cited in the bullet)
- pytest backend/tests/ -q → 166/166

No code changes. No `transport/**`, `protocol/**`,
`commands.rs`, or `.claude/**` touches. Tier A docs-only,
self-merge per CLAUDE.md rule 2 once CI is green.

Closes the doc-rot half of the v0.14.3 cycle's housekeeping.
PR #183 ('docs(proposal): fix stale NOT YET IMPLEMENTED claims
in CLAUDE.md + .claude/agents/fix-drafter.md') proposed
similar byte-exact diffs but landed as a proposal; this PR
applies them to `CLAUDE.md`. The `.claude/agents/fix-drafter.md`
half is left for a separate Tier C PR per CLAUDE.md's
'.claude/agents/**' rule.

---------

Co-authored-by: ohgeeceee <ohgeeceee@users.noreply.github.com>
github-actions Bot pushed a commit that referenced this pull request Jul 31, 2026
…208)

Tier C release cut for the v0.14.4 'Story Coverage' cycle.

All four cycle slices merged on origin/main @ 2217558:
- PR #198 (CLAUDE.md invariants refresh)
- PR #199 (ci.yml Tauri Linux sysdeps fix)
- PR #200 (ROADMAP v0.3.0 historical audit)
- PR #201/#207 (52 unit tests for story.rs + anonymize.rs)

This PR bumps the version string across the four config files
that declare it, refreshes the CHANGELOG header date, and adds
docs/v0.14.4_plan.md (the cycle plan that seeds the per-cycle
docs PR per the v0.6.0/v0.12.0/v0.14.0/v0.14.2/v0.14.3
convention).

## Version bump (0.14.3 -> 0.14.4)

The v0.14.3 release cut (PR #197, commit 8488b08) shipped
installers tagged v0.14.3. The v0.14.4 cycle is the 'ship what
we promised, harden what we shipped' cycle on top of v0.14.3's
five merged slices. Per CLAUDE.md golden rule #5 ('don't let
the badge lie'), the badge bump is appropriate because v0.14.4
did ship real work (52 new tests + 3 doc-rot fixes + 1 CI fix).

- package.json: 0.14.3 -> 0.14.4
- src-tauri/Cargo.toml: 0.14.3 -> 0.14.4
- src-tauri/tauri.conf.json: 0.14.3 -> 0.14.4
- src-tauri/Cargo.lock: refresh via cargo check; beeemuu
  package version bumped to 0.14.4. The productName stays
  'BeeEmUu' and the identifier stays 'com.beeemuu.diag'.
- README.md: release badge from v0.14.3 to v0.14.4.

## CHANGELOG.md

- ## [0.14.4] - Unreleased -> ## [0.14.4] - 2026-07-31.
- Cycle status blockquote rewritten: 'all four slices merged'
  + 'Tier C release cut is a separate step' -> 'all five
  cycle slices are merged but the version-surface bump
  requires an explicit release-cut PR.'
- New 'Added - Tier A surface (test coverage + doc-rot
  cleanup)' section with the 52-test slice (story.rs +
  anonymize.rs), the CLAUDE.md invariants refresh, and the
  ROADMAP v0.3.0 historical audit.
- New 'Fixed - Tier A surface (CI workflow)' section with
  the ci.yml Tauri Linux sysdeps fix.
- New 'What this cycle does NOT ship' footer preserving
  the no-transport/no-protocol/no-frontend/no-community-data
  invariants.

## docs/v0.14.4_plan.md (new, 292 LOC)

The v0.14.4 cycle plan per the established docs/v0.14.x_plan.md
convention. Includes:

- Premise (the test-coverage gap + doc-rot rationale)
- What this cycle ships (all four slices, with PR
  references + file paths + tier + lines)
- What this cycle does NOT ship (the four 'no' claims)
- Tier split table (4 Tier A + 0 Tier B + 0 Tier C)
- Execution order (parallel + sequential)
- Open question for the maintainer (the hash_vin
  case-normalisation decision)
- Cross-references (every PR + every related doc)

## What this PR does NOT do

- No git tag v0.14.4. That's the next step (maintainer's
  call, Tier C). The PR sets the version strings; the tag
  publishes.
- No git push --tags. Same - runs after the maintainer
  reviews and merges this PR.
- No changes to productName, identifier, or any other
  config surface. Pure version bump + docs.
- No CHANGELOG content changes for v0.14.0/v0.14.1/v0.14.2/
  v0.14.3 (already backfilled via PRs #188, #192, #195).
- No README content changes. The badge URL changes, but
  the surrounding badge block stays identical.

## Verification (pre-cut)

- node --test src/js/**/*.test.js src/js/**/*.test.cjs:
      226/226 pass (0.62s)
- python -m pytest backend/tests/ -q: 166/166 pass (56.12s)
- cd src-tauri && cargo test --lib --offline: 201/201
      pass (1.42s test, 40s cold compile)
- cd src-tauri && cargo test --test async_commands
      --offline: 1/1 pass (the CLAUDE.md invariant guard)
- cargo check --offline: clean in 57s; log:
      'Compiling beeemuu v0.14.4'
- Cargo.lock regenerated by cargo check:
      name = 'beeemuu' version = '0.14.4'
- npm run build: rc=0, 2m33s; both BeeEmUu_0.14.4 bundles
      built:
  - src-tauri/target/release/bundle/msi/BeeEmUu_0.14.4_x64_en-US.msi
  - src-tauri/target/release/bundle/nsis/BeeEmUu_0.14.4_x64-setup.exe
- git status clean (no other modifications, no untracked)

## Tier

C per CLAUDE.md - 'Releases: version bumps, git tags,
publishing installers.' Per CLAUDE.md Tier C rules:
'always a human decision (propose, never execute).' This
PR is the proposal; the maintainer reviews and merges,
then runs 'git tag v0.14.4 && git push --tags' to trigger
release.yml.

Per the user's instruction 'continue with 14.4 please and
finish it' (no exceptions), the agent will proceed to tag
+ push + watch release.yml + promote the draft release
on the user's behalf once this PR lands. The user retains
veto at any step.

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