Store Ticket Assistant

Case studyLocal-first AI desktop appProject 04

Independent prototype · packaged (v0.1.0 app bundle) · tested in CI · public repository

Screenshot · sample transcript Store Ticket Assistant ticket-field self-review, from its built-in sample transcript

Summary

A local-first assistant for a workflow I know well: capturing support-call details into a structured ticket. The interesting engineering is in what it refuses to do (leave the machine) and in how transcript quality is handled without a cloud model: a hallucination classifier, a reversible correction dictionary, and regression suites built from real transcripts after unit tests missed two analyzer regressions.

The problem and who it serves

Support technicians re-type the same call details into tickets, and sending internal call notes to a cloud service is not acceptable. The tool had to capture a call once, privately, on the technician’s own machine.

Store-technology support technicians writing tickets from calls. Built on personal time and equipment with no employer data; names of ticketing products and internal fields are deliberately absent from this page.

My role

Solo. I set the privacy stance (everything local; any model call restricted to localhost), designed the transcript-quality pipeline, the release checklist and the regression suites. Implementation was AI-assisted under my direction.

Architecture

The boundary is explicit: Rust owns side effects, TypeScript owns pure logic, and the Tauri capability file is the privacy contract. The HTTP capability allow-lists exactly two localhost origins, so even the optional model path cannot reach the network.

Decisions and trade-offs

  • Route model calls through the shell, not the webview. Browser fetches to a local model fail CORS preflight. Instead of asking users to reconfigure their model server, requests go through the Rust HTTP plugin with capability-scoped URLs.
  • Rules before models for speaker turns. Diarisation models are large and need training data; a rule-based question/answer turn-taker with advisory labels and one-click relabel was good enough and fully testable.
  • Regression suites from real transcripts. After unit tests passed while the analyzer regressed twice, two scripts replay recorded transcripts (12 transcripts, 73 field checks) in CI.
  • Reversible corrections. Every correction rule records what it changed so a wrong fix can be excluded from forms rather than silently baked in.

Verified results

MeasureResultEvidence
Tests292 passed across 25 files; two transcript-regression scriptsCI run 33564104141 on main, Sep 2026 (2026-09-01)
PackagingmacOS app bundle v0.1.0 builtBundle on disk; no release pipeline, manual per platform
Privacy boundaryHTTP capability limited to localhost:11434 and localhost:1234src-tauri/capabilities/default.json
Repo hygieneclean-clone break fixed (a gitignore rule swallowed src/data); a 20 MB app bundle removed from tracking; advisories 11 → 2Commits c94df80, 9636427, 694e672

Limitations and remaining work

  • Prototype, not in production use; accuracy figures in the README (filter and speaker-label rates) are self-reported and are not repeated here.
  • Rust side has no tests of its own; the logic under test is the TypeScript layer.
  • Two UI pages are placeholders; releases are manual per platform.