feat(v0.10.0): plan verification badge in walkthrough header (Tier A) - #127
Conversation
Completes the data contract PR #5 installed: the plan's meta.verified marker now flows end-to-end and renders as a badge. Rust (src-tauri/src/testplans.rs, additive, non-protected data loader): - PlanMeta gains verified: Option<String>; TestPlan gains verified: Option<String>; to_plan threads it through. Legacy plans with no marker parse as None and render no badge. - parse_roundtrip test asserts the marker threads through; shipped corpus + gate tests still green. UI (src/js/main.js, src/index.html, src/css/app.css): - loadTestPlan reads plan.verified and renders a header badge: NEEDS VERIFICATION (amber, default) or ✓ Verified (green). Absent marker => no badge. Light + dark themes. - plan_verified_state() maps the TOC string to label+class. CHANGELOG: 0.10.0 section. Tier A (frontend + data loader; no protected path). Verification: cargo test testplans (5/5), node --test (56), lint-toml (0 problems).
|
ECC bundle files are already tracked in this repository. Skipping generation of another bundle PR. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 914ff145d7
ℹ️ 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".
| // default on every plan; "verified" only after a real-car harness walk | ||
| // (docs/validation/testplans.md). Absent => no badge (pre-PR-#5 plans). | ||
| if (verifiedEl) { | ||
| const v = plan_verified_state(plan ? plan.verified : undefined); |
There was a problem hiding this comment.
Move badge rendering after the plan lookup
When any DTC row is clicked, this expression reads plan, but that binding exists only inside the later try block. It therefore throws ReferenceError: plan is not defined before get_test_plan is invoked and outside the error handler, causing loadTestPlan (and the surrounding Promise.all) to reject while the walkthrough remains stuck. Render the badge after the awaited plan has been retrieved.
Useful? React with 👍 / 👎.
| and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). | ||
|
|
||
| ## [Unreleased] | ||
| ## [0.10.0] |
There was a problem hiding this comment.
Keep these changes unreleased until versions are bumped
Changing the heading to 0.10.0 declares these accumulated changes released, but package.json, src-tauri/Cargo.toml, src-tauri/tauri.conf.json, and the application entry in Cargo.lock all still identify the product as 0.6.0 (as does the README's latest-release section). Consequently, any artifact built from this commit is still packaged and reported as 0.6.0 despite the changelog claiming 0.10.0, which can break release identification and updater version comparisons. Retain the Unreleased heading here or perform the repository's standard coordinated release-version bump.
Useful? React with 👍 / 👎.
Cargo.toml, package.json, and tauri.conf.json all still said 0.6.0 while the actual release line is at v0.9.0 (Guided Fault Finding, 5/5 slices merged) and v0.10.0 (plan verification badge, PR #127). Bumps the three build-version strings to 0.10.0 so the produced MSI/NSIS bundles carry the correct label. No code change. Verified: npm run build compiles clean and now emits BeeEmUu_0.10.0_x64 bundles. Tier A (config-only). Co-authored-by: hermes-agent <ohgeeceee@users.noreply.github.com>
v0.10.0 follow-up to the plan verification badge (#127). - The NEEDS VERIFICATION badge now opens the real-car validation harness doc (docs/validation/testplans.md) on click — the procedure to upgrade a plan. VERIFIED shows a static green tag. Uses the app's existing external-link pattern (window.open target=_blank noopener). - Fixes a latent TDZ bug from #127: loadTestPlan previously read plan.verified before the plan was resolved (ReferenceError at runtime; unit tests never exercised loadTestPlan). The badge now renders after get_test_plan resolves, via a new renderPlanVerifiedBadge() helper. - plan_verified_state() now carries the harness href + tooltip. - Fixed the about modal's stale repo owner (ohjoncurrie -> ohgeeceee, the canonical owner confirmed via git remote + gh repo view + gh pr view). Tier A. Verified: npm run build compiles clean; node --check main.js OK; node --test 56 pass. Co-authored-by: hermes-agent <ohgeeceee@users.noreply.github.com>
…147) * feat(v0.12.0): recurring-DTC callout under the fault table (slice 5) Slice 5 of v0.12.0 Fault Memory (docs/v0.12.0_plan.md): the 'headline UI moment of the cycle'. After a successful DTC read, if the local history has past occurrences of any code the user just saw, surface a 'seen before' banner under the fault table. Pure frontend Tier A — no Rust / commands.rs / transport / protocol change. Frontend: - New src/js/recurring_dtc.js pure-data module. computeCallout( currentDtcs, history, nowMs) returns either null (no banner) or a sorted list of CalloutEntry rows {code, occurrences, last_seen_iso, last_seen_human, first_seen_iso, first_seen_human, same_address}. Default lookback is 14 days. Multiple buckets for the same code across addresses collapse into one row with summed occurrences. Entries older than the window are filtered out. Includes a relativeTimeLabel helper (today / yesterday / Nd ago / YYYY-MM-DD) that prefers day-relative labels over hour-relative ones for the same-UTC-day case. - main.js renders the callout: renderHistoryCallout(dtcs) queries the history via window.beeemuuDtcHistory.queryDtcHistory(vin, null), hands the summary + current DTCs to computeCallout, and toggles a #fault-history-callout div under the fault table. Best-effort: any failure hides the banner silently rather than breaking the DTC read flow. Empty reads skip the query entirely. - index.html: new <div id="fault-history-callout" class="hidden"> with a <ul id="fault-history-callout-list"> for the entries, plus the new <script src="js/recurring_dtc.js"> tag. - src/css/app.css: amber callout styling (matches the NEEDS VERIFICATION badge palette from v0.10.0 #127 so the visual language stays consistent: 'this needs your attention'). Tests: 26 new unit tests under node --test covering empty inputs, no-match cases, 14-day window filter, custom windowMs override, multi-address aggregation (same code, different modules collapses into one row with summed occurrences), most-recent-last_seen selection across buckets, same_address flagging, sort order, unparseable timestamps, and the relativeTimeLabel helper's edge cases (just now / Nm ago / today / yesterday / Nd ago / YYYY-MM-DD). Caught + fixed 1 bug in my own implementation during the test loop (skill #4 verify-then-claim): the original priority order returned '11h ago' for an 11-hour-old timestamp on the previous UTC day, but 'yesterday' carries more information. Fixed the priority so day-relative labels take precedence over hour-relative labels, and updated the corresponding test. Verification: - node --check on all changed files: pass. - node --test 'src/js/**/*.test.js' 'src/js/**/*.test.cjs': 148 pass, 0 fail (was 122 before this PR — the 26 new recurring_dtc tests). Tier A — frontend only, no protected paths. Self-merge when CI green. * fix(v0.12.0): make DTC history commands async + spawn_blocking PR #144's three new commands (record_dtc_read, query_dtc_history, clear_dtc_history) shipped sync. The static allowlist test (tests/async_commands.rs) caught this on PR #147's CI run: the project invariant from CLAUDE.md §4 is 'any #[tauri::command] that touches serial or network transport MUST be async fn, or offload via spawn_blocking' — and the explicit allowlist is for purely-local commands like export_text (grandfathered). New commands that touch disk should follow the project direction, not the grandfather. Converting to async + spawn_blocking: - record_dtc_read -> async, spawn_blocking wraps record_dtc_read_impl. Per-line append is microseconds; the spawn_blocking cost is amortised over the whole batch. - query_dtc_history -> async, spawn_blocking wraps query_dtc_history_impl. - clear_dtc_history -> async, spawn_blocking wraps clear_dtc_history_impl. The _impl fns stay sync (and the unit tests still pass against them directly), matching the same pattern as discover_enet_targets in commands.rs. The JS-side wrapper (src/js/dtc_history.js) and the rest of slice 5 (recurring_dtc.js, main.js wiring) are unchanged. The wire surface from the renderer's perspective is identical — the only difference is that the IPC call returns a Promise that resolves after the spawn_blocking thread finishes. Verification: - cargo test --lib: 124 passed, 0 failed. - cargo test --test async_commands: 1 passed, 0 failed (only_allowlisted_commands_may_be_sync now passes). - Full cargo test: 124 + 1 + doc-tests, all green. - npm run build: clean (MSI + NSIS bundles built). No frontend changes — this is a Tier B fix on the slice 2 commands only, keeping the v0.12.0 Tier B surface area minimal. --------- Co-authored-by: Jon currie1 <ohgeeceee@users.noreply.github.com>
…der claim (#182) Two small doc-rot fixes from the same audit that found the v0.15.1/v0.16.0/v0.16.3/v0.16.5 false claims in the forward roadmap (PR #181): 1. community/testplans/README.md:33 — 'UI rendering lands in a follow-up' was wrong. The walkthrough verification badge is shipped in the desktop app (src/js/main.js renderPlanVerifiedBadge, PR #127) and in the standalone walkthrough HTML bundle (src/js/walkthrough_bundle.js buildBundleHtml, PR #127/#130). The README now points at both rendering sites. 2. community/freeze/README.md:68 — the reference to 'docs/validation/freeze-frame.md harness (planned v0.14.1)' was stale: the doc didn't exist. v0.14.1 shipped without it. This PR ships the missing harness doc + updates the README reference. The new docs/validation/freeze-frame.md mirrors the n62-real-car.md (PR #178) and can-broadcast.md (PR #164) shape: 5 steps, copy-pasteable GitHub issue template, a 'Verification results' closeout, and explicit cross-references. The per-ECU schema format (offset, width, scale, bias) is already documented in community/freeze/README.md and referenced verbatim. The DME/DSC/FRM freeze-frame byte-0..2 convention (engine speed u16 BE + coolant byte - 40) is the only portion that's shared across all three simulator fixtures and chassis-validated today; offsets 3-8 remain unverified and the harness doc is explicit about the 'do-not-invent-meaning' discipline. Tier A, no test impact, no code changes. Auto-merge on CI green per CLAUDE.md rule 2. Co-authored-by: ohgeeceee <ohgeeceee@users.noreply.github.com>
Summary
v0.10.0 — Plan verification badge (Tier A frontend + data loader). Completes the data contract PR #5 installed: the
meta.verifiedmarker incommunity/testplans/*.tomlnow flows all the way to the walkthrough header as a badge.This PR is Tier A — frontend + an additive change to the non-protected
testplans.rsdata loader. No protected paths (transport/protocol/commands.rs) touched.What it does
meta.verified:"needs verification"state every plan ships with.docs/validation/testplans.md).Structure
Rust (
src-tauri/src/testplans.rs) — additive:PlanMetagainsverified: Option<String>;TestPlangainsverified: Option<String>;to_planthreads it through. Nodeny_unknown_fields, so plans without the marker still parse asNone.parse_roundtrip_maps_all_fieldsnow asserts the marker threads through;shipped_testplans_branch_integrityandshipped_corpus_loadsstill green.UI (
src/js/main.js,src/index.html,src/css/app.css):loadTestPlanreadsplan.verifiedand renders#walkthrough-verified;plan_verified_state()maps the TOML string to label + class. Light + dark themes, matching the existing.unverified-tagamber convention.Verification
cargo test --lib testplans→ 5 passed (parse roundtrip, did range, shipped corpus load, case-insensitive query, branch-integrity gate).node --test src/js/test/*.test.cjs→ 56 passed (unchanged).node scripts/lint-toml.js→ 0 problems (35 files).node --check src/js/main.js→ exit 0.Files