Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 15 additions & 14 deletions ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,7 @@ headers, auto-share).

---

## v0.12.0 — "Fault Memory" (Planned)
## v0.12.0 — "Fault Memory" (Released)

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 Do not mark v0.12.0 released before its release cut

At this commit, both package.json:3 and src-tauri/Cargo.toml:3 still declare version 0.10.0, and there is no v0.12.0 release-note or version-bump change. The repository also distinguishes a closed feature cycle from the Tier-C release cut, as demonstrated by the closed v0.11.0 cycle above remaining labeled Started. Labeling this cycle Released therefore tells users that a v0.12.0 build exists when only its feature slices have merged; keep it labeled as closed/started until the actual release cut lands.

Useful? React with 👍 / 👎.


**Premise.** Closing the DTC panel is closing the diagnosis. Today `lastDtcs` is a per-session cache; once the user quits the app, the DTCs are gone. v0.12.0 persists every DTC read to a local JSONL log and surfaces a **Fault Memory** panel: "this DTC has appeared N times over the past K days on this car". Local-only, opt-in, no cloud, no privacy surprise. See
[`docs/v0.12.0_plan.md`](docs/v0.12.0_plan.md) for the full cycle plan, including the explicit "what we will NOT do" list (cloud sync, ML prediction, per-entry editing, CSV export).
Expand All @@ -349,28 +349,29 @@ headers, auto-share).

| Item | Status | Tier | Notes |
|------|--------|------|-------|
| Cycle plan + ROADMAP v0.12.0 header | 🔲 Open | A | This PR lands the plan on `main`. Docs-only. |
| `record_dtc_read` / `query_dtc_history` / `clear_dtc_history` Tauri commands | 🔲 Open | **B** | Three additive commands in `commands.rs` only (no `transport/` / `protocol/` changes). Local JSONL appender at `~/beeemuu-exports/dtc-history.jsonl`. 60 s dedup window. Tier B — flag `commands.rs` at the top of the PR body, wait for human merge. |
| `src/js/dtc_history.js` pure module + tests | 🔲 Open | A | Wraps the three Tauri commands. In-memory mock store for tests under `node --test`. Dual export (CommonJS + `window.beeemuuDtcHistory`). |
| Recording wired into `readFaults()` + opt-in toggle in Settings | 🔲 Open | A | Hooks the existing `read_faults` invocation; toggles recording on/off; surfaces file path in the panel header. |
| "Recurring DTC" callout in the DTC panel | 🔲 Open | A | The headline UI moment of the cycle. When `lastDtcs.length > 0`, queries history for the current VIN and renders a banner under the DTC table. Pure read, frontend only. |
| `docs/validation/dtc-history.md` harness doc | 🔲 Open | A | Same shape as `docs/validation/testplans.md` and `docs/validation/service-functions.md`: file location, line format, clear procedure, dedup window, "no VIN" caveat. |
| Cycle plan + ROADMAP v0.12.0 header | ✅ Done (PR #143) | A | `docs/v0.12.0_plan.md` + this ROADMAP entry. Docs-only. |
| `record_dtc_read` / `query_dtc_history` / `clear_dtc_history` Tauri commands | ✅ Done (PR #144) | **B** | Three additive commands in `commands.rs` only (no `transport/` / `protocol/` changes). Local JSONL appender at `~/beeemuu-exports/dtc-history.jsonl`. 60 s dedup window. Flagged `commands.rs` at the top of the PR body. |

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 Record the protocol change made by PR #144

PR #144 (e9ba6e3) was not limited to commands.rs: it also changed src-tauri/src/protocol/mod.rs to import Deserialize and derive it for Dtc so the new IPC argument can be decoded. Describing the slice as commands-only, and later claiming zero protocol changes, makes the shipped-history record factually incorrect and hides that a protected protocol path participated in this cycle; update both statements to mention the additive Dtc derive.

Useful? React with 👍 / 👎.

| `src/js/dtc_history.js` pure module + tests | ✅ Done (PR #145) | A | Wraps the three Tauri commands. In-memory mock store for tests under `node --test`. Dual export (CommonJS + `window.beeemuuDtcHistory`). |
| Recording wired into `readFaults()` + opt-in toggle in Settings | ✅ Done (PR #146) | A | Hooks the existing `read_faults` invocation; toggles recording on/off; surfaces file path in the panel header; persists the toggle via the v0.7.0 `workspace.json`. |
| "Recurring DTC" callout in the DTC panel | ✅ Done (PR #147) | A | Headline UI moment of the cycle. When `lastDtcs.length > 0`, queries history for the current VIN and renders a banner under the DTC table. Pure read, frontend only. 14-day lookback; collapses occurrences across modules for the same code. |

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 Keep VIN-less history from blending different cars

When the user has not clicked Read vehicle, renderHistoryCallout passes null as the current VIN, and group_history_lines treats a None filter as no filter at all, returning entries for every VIN in the shared history file. The supposedly completed callout can therefore tell a multi-car user that a fault was previously seen on the current car when it only occurred on another car. Suppress the callout until a VIN is known or make the null-VIN query select only null-VIN records before marking this slice done.

Useful? React with 👍 / 👎.

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 Restrict occurrence counts to the stated 14-day window

renderHistoryCallout queries history with since_iso: null, so Rust groups every occurrence ever recorded into each bucket; computeCallout then checks only whether the bucket's latest timestamp is within 14 days without removing older occurrences from its count. If a code has old history plus one recent occurrence, the completed UI reports the all-time total as having appeared "in the past 14 days." Pass the cutoff into queryDtcHistory or otherwise aggregate only in-window records before claiming a 14-day lookback.

Useful? React with 👍 / 👎.

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 Exclude the current read from the seen-before decision

With history recording enabled, readFaults() awaits recordDtcRead before querying and rendering the recurring-DTC callout. A fault's first-ever observation is therefore appended and immediately returned as one matching occurrence, causing the "seen before" banner to appear even though there was no prior history. Query before recording or explicitly exclude the just-appended observation so this slice implements its stated recurring-fault behavior.

Useful? React with 👍 / 👎.

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 Pass the selected module into the callout computation

The Dtc objects returned by read_faults contain no address, yet computeCallout decides same_address by comparing d.address with each history entry. Because renderHistoryCallout passes those raw DTCs without attaching selectedAddress, every real callout is labeled "different module," including history from the module currently being read. Supply the selected address separately or decorate the current DTCs before marking the cross-module behavior done.

Useful? React with 👍 / 👎.

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 Clear stale callouts when a read returns no faults

After a callout has been displayed, selecting a fault-free module makes readFaults() return from the empty-DTC branch before renderHistoryCallout gets a chance to hide and clear the existing banner; read failures have the same problem. The old module's "seen before" result consequently remains visible beneath a table that now says no faults are stored. Hide the callout at the start of each read, including empty and failure paths, before treating the DTC-panel integration as complete.

Useful? React with 👍 / 👎.

| `docs/validation/dtc-history.md` harness doc | ✅ Done (PR #148) | A | Same shape as `docs/validation/testplans.md` and `docs/validation/service-functions.md`: file location, line format, clear procedure, dedup window, "no VIN" caveat, storage growth, privacy note. |
| Async conversion follow-up (PR #147 fixup) | ✅ Done | **B** | The slice-2 commands shipped sync. PR #147's CI run caught this against the `tests/async_commands.rs` allowlist guard; follow-up commit converted the three commands to `async fn` + `spawn_blocking`, matching the project's stated direction for new commands touching disk. |

Slices dispatch as PRs when the work completes — no Discussion gate
(`COMMUNITY_FRAMEWORK.md` Rule 2). Slice 2 is the gating PR for the
Rust commands; slices 4 and 5 depend on it. Slices 1 and 3 can land in
parallel with slice 2 (slice 3 uses an in-memory mock). Slice 6 lands
any time after slice 1.
(`COMMUNITY_FRAMEWORK.md` Rule 2).

**Cycle closed 2026-07-23.** All 6 v0.12.0 slices shipped across 6 PRs (#143, #144, #145, #146, #147, #148). "Fault Memory" — the cycle of making the app remember your car between sessions — is done. Local JSONL at `~/beeemuu-exports/dtc-history.jsonl`; opt-in toggle on the Fault memory panel; "seen before" callout under the DTC table. Zero new cloud deps, zero new crate deps, zero changes to `transport/` or `protocol/`.

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 cycle open until history clearing is wired

The v0.12.0 plan promises a confirmed Settings → Clear action for clear_dtc_history, but a repo-wide search at this commit finds no UI caller of clearDtcHistory; the shipped guide explicitly says there is no in-app button and calls it a follow-up. The toggle's status message nevertheless tells users to "Clear via Settings," leaving them with no such action. Track that follow-up as unfinished or wire the button before declaring every planned slice shipped.

Useful? React with 👍 / 👎.


---

## Ready to Claim (🟢 — open a PR when you want it)

These items have lived on the ROADMAP for multiple cycles as 🟢-
Ready and have not been claimed. They're real, well-scoped, and not
in conflict with the active v0.11.0 cycle. (PNG export landed in
v0.11.0 #131; SVG export is tracked under v0.11.0; the row below
covers anything else in this category.)
in conflict with the active v0.13.0 cycle (or whatever the next
cycle lands on). (PNG/SVG export landed in v0.11.0 #131 / #136; CSV
Comment on lines +371 to +372

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 Do not claim an undefined v0.13.0 cycle is active

There is no v0.13.0 plan, header, or other v0.13.0 reference anywhere in this commit, so the Ready-to-Claim section cannot assert that its items do not conflict with an "active v0.13.0 cycle." The parenthetical acknowledging that the next cycle may be something else does not restore that conflict guarantee; refer neutrally to the next cycle until its scope is actually defined.

Useful? React with 👍 / 👎.

units + walkthrough bundle in #138 / #142; DTC history in v0.12.0
#143–#148; the row below covers anything else in this category.)

> **If you're new to the project, start here.** These are the lowest-
> risk ways to land a first PR.
Expand Down
Loading