ZyVOP Logo
Content That Connects
SeriesAI NewsWhy ZyVOPJoin Discord
ZyVOP Logo
Content That Connects

Empowering developers and creators with cutting-edge insights, comprehensive tutorials, and innovative solutions for the digital future.

Content

  • Categories
  • Tags
  • Badges
  • Leaderboard
  • Write Article
  • Newsletter

Company

  • About Us
  • Why ZyVOP
  • API Documentation
  • Write for Us
  • Contact

Connect

  • Privacy Policy
  • Terms of Service
  • Cookie Policy
  • DMCA Policy
  • Code of Conduct

© 2026 ZyVOP. Crafted with care for the developer community.

Made with ❤️ by the ZyVOP team
All systems operational
HomeUnknown Is Not Zero: Building ParkinSUM to Refuse False Precision

Unknown Is Not Zero: Building ParkinSUM to Refuse False Precision

How a fixed-threshold Flutter prototype became a provenance-first, deterministic educational engine.

Albert Zhou
Albert ZhouSenior Developer
August 17, 2026
7 min read
Unknown Is Not Zero: Building ParkinSUM to Refuse False Precision
Article
👍2

In April 2026, my ParkinSUM prototype saved a meal and ran one food–medication conflict check.

The first calculation used fixed weights and thresholds. It could produce a result, but the inputs soon became harder than the formula. If a record said levodopa 100, did 100 mean milligrams, tablets, or something else? If protein data was missing, was that the same as zero grams? If meal timing was unknown, could a timing-based rule return an honest result?

The difficult problem was no longer producing an answer; it was deciding whether the app had earned the right to produce one.

That question changed ParkinSUM's architecture. ParkinSUM Companion is now a local-first Flutter prototype for Parkinson's disease diet–medication education. Its public demonstrations use synthetic or sample data, and it does not provide medication, timing, dietary, or treatment advice.

The simple version was too certain

The earliest preserved version used a simplified conflict heuristic. It applied fixed penalties to meal composition and timing, then returned a conflict signal. Editable meal-time context came next, followed by a separate next-meal recommendation pipeline that remained deliberately conservative.

Each feature exposed the previous feature's limits. A fixed threshold can be deterministic and readable while remaining wrong for the available context. Timing changes the interpretation, formulation changes the relevant window, and missing nutrients change what the engine can calculate at all.

The biomedical evidence also required restraint. Official labeling states that levodopa competes with certain amino acids for transport and that high-protein meals may impair absorption in some patients. The same label reports substantial variation within and between individuals, while clinical records suggest that noticeable protein interactions occur in a subset of patients rather than uniformly (DailyMed; Virmani et al., 2016).

A single cutoff flattened those limits, so ParkinSUM needed to model context without presenting an educational simulation as a personal prediction.

Deterministic did not mean correct

A data-fidelity audit exposed three silent assumptions. None involved an LLM, and every output remained repeatable, yet deterministic code still handled uncertain data too confidently.

First, several USDA nutrient identifiers were wrong. Leucine pointed to 507 instead of 504, isoleucine to 506 instead of 503, and threonine to 503 instead of 502. The corrected extractor maps the verified FoodData Central sequence from 501 through 512 and protects each mapping with regression tests (extractor).

Second, a legacy model stored unavailable nutrient values in non-nullable numeric fields. A missing protein value could therefore travel through the pipeline as 0 g, producing a number that described the data structure rather than the food (regression tests).

Third, two runtime paths supplied a hard-coded 100 mg default when no explicit medication dose was available. The default kept the orchestrator and database-backed meal check running, but its precision did not come from user input. The corrected parser now requires an explicit value–unit pair (dose parser).

These failures changed the design goal because determinism was necessary for reviewability but insufficient for data fidelity.

Missing data became a control-flow decision

The central rule is now simple: unknown is not zero. ParkinSUM preserves missingness through normalization, then lowers context completeness, widens uncertainty, or blocks the relevant calculation.

Input state

Tempting shortcut

ParkinSUM behavior

Protein value unavailable

Store 0 g

Preserve null, record the missing field, and lower completeness

levodopa 100

Assume 100 mg

Reject dose-dependent interpretation because the unit is absent

Formulation or release type missing

Choose a common default

Mark the context insufficient for formulation-sensitive rules

Meal-time window absent

Invent a convenient time

Do not activate the window-based ranker

Source provenance absent

Trust the parsed value

Block promotion into evidence-linked rule evaluation

This distinction affects more than display copy. A missing protein field becomes null inside the meal component, and the composition normalizer records that omission. Later layers receive a lower completeness score, while a measured zero remains zero and stays distinct from unavailable data.

The medication path applies the same principle. A dose parser accepts one unambiguous value–unit pair, such as 100 mg, while bare numbers, unitless names, empty notes, and ambiguous combinations remain unavailable for dose-dependent interpretation.

A warning in the interface is not a safety boundary if the computation has already guessed.

The gate comes before the engine

ParkinSUM moved uncertainty ahead of rule evaluation. Its medication gate requires an active ingredient, product variant, strength, unit, form, route, release type, jurisdiction, and source reference.

The validator returns one of three states: valid, insufficient, or invalid. Only valid, normalized context can enter the relevant rule path; the other states explain why no rule fired (validator).

The core branch is intentionally small:

if (issues.isNotEmpty) {
  return MedicationContextValidationResult(
    validity: hasInvalidatingIssue
        ? MedicationContextValidity.invalid
        : MedicationContextValidity.insufficient,
    issues: List.unmodifiable(issues),
    normalized: null,
    safeUserCopy: _safeInvalidCopy,
  );
}

This is a fail-closed design. Here, fail-closed does not mean that the app is clinically safe; unsupported input instead produces an explicit refusal state rather than a fabricated score.

structured input
      |
      v
context validation ---- insufficient / invalid ----> no conflict result
      |
      | valid
      v
normalization ----> deterministic engine ----> evidence trace ----> educational output

The decision core has no LLM

The conflict engine remains deterministic by design. The same structured input follows the same rule path, produces stable identifiers, and exposes every field used in the calculation.

Each RuleExplanation records the rule ID, triggered conditions, input fields, source references, missing inputs, limitation text, output type, and direct not-advice boundary. Reviewers can therefore inspect both what fired and why another rule stayed silent (explanation schema).

Optional local AI may polish wording or reorder an already filtered candidate set. It cannot create a conflict, change hard-rule scores, or add candidates. Network, JSON, or contract failures fall back to the deterministic output.

This separation avoids a false choice between readable language and auditable decisions because the model may phrase an explanation without becoming the source of truth.

ParkinSUM conflict explanation with evidence-oriented trace and educational boundaries

One threshold became a time axis

The first heuristic treated interaction as a few fixed bands, while the current engine represents meal and medication events on a shared minute-level timeline.

The pipeline normalizes meal composition, estimates an illustrative gastric-emptying profile, defines a literature-informed levodopa absorption-opportunity window, and models large neutral amino acid competition. These layers describe directional mechanisms without predicting a person's blood concentration, motor response, or treatment outcome.

Multiple levodopa events are evaluated separately. Deterministic maximum-overlap aggregation prevents a high-overlap event from disappearing inside an average, while every event keeps its own trace. Other medication events remain outside this levodopa-specific layer.

The next-meal scorer also avoids choosing one convenient time. It samples 5–12 deterministic points across a user-defined window, then uses worst-case modeled overlap for ordering. Best, mean, and per-sample values remain available for review.

Source quality travels with the calculation. Actual FoodData Central amino-acid fields take priority when present, while a protein-source proxy remains a documented fallback. Partial or weaker-provenance data widens uncertainty rather than raising confidence.

The resulting model is more detailed, but its most important branch still returns insufficient_context (model documentation).

ParkinSUM next-meal results using synthetic candidates and a user-defined window

A dead button revealed a runtime boundary

One early failure looked like a user-interface bug. Pressing “Save meal and check conflict” appeared to do nothing, so I first inspected the button area and feedback overlay.

Runtime logs contradicted that diagnosis. The callback had fired, but the save path crashed while generating an ID from Random().nextInt(1 << 32).

Dart uses JavaScript's native bitwise behavior on the web. Those operands are truncated to 32 bits, so values near the boundary can behave differently from native targets. In this case, 1 << 32 became 0, which turned ID generation into nextInt(0) (Dart number representation; Random.nextInt).

The patch used a web-safe 1 << 31 range and combined the random value with a microsecond timestamp (current implementation):

- final r = Random().nextInt(1 << 32);
- final now = DateTime.now().millisecondsSinceEpoch;
+ final r = _idRandom.nextInt(1 << 31);
+ final now = DateTime.now().microsecondsSinceEpoch;

The important correction was not the one-line change; instrumentation replaced a plausible interface story with a runtime trace that isolated a cross-platform assumption.

Tests must cover refusal

Most test suites ask whether a feature works, while ParkinSUM also tests whether a feature refuses inputs that cannot support the requested interpretation.

The public v0.2.0-beta mechanistic replay suite contains 41 synthetic scenarios. Cases cover valid context, missing nutrients, unitless doses, multiple medication events, overlapping meals, source-quality changes, and formulation provenance. Each run records the expected output type, severity ceiling, confidence ceiling, blocked mechanisms, source references, and failure reason (replay guide).

The replay runner also scans every generated explanation for prescriptive phrases. Text such as “change your dose,” “avoid protein,” or “recommended timing” fails the run, creating a code-level wording boundary rather than evidence of clinical safety.

Additional checks cover Firestore rules, public claims, local privacy, localization copy, source access, and source-version drift. These checks establish deterministic behavior and preserved boundaries, but they do not establish medical accuracy or patient benefit (verification guide).

The May 28 fidelity correction reported 310 passing tests and 32 successful replay scenarios at that development point. The public beta later expanded the replay inventory to 41 cases, measuring broader regression coverage rather than clinical accuracy (fidelity commit).

What changed

The main improvement was not a higher score; it was a more honest relationship between inputs, computation, and output.

First preserved prototype

Public beta design

Fixed-weight conflict heuristic

Context-gated, literature-informed time-axis simulation

Limited meal-time semantics

Recorded events plus a user-defined time window

Missing data could inherit numeric defaults

Missing values remain unknown and lower confidence

Hard-coded dose default kept the path running

Dose-dependent logic requires explicit user-entered value and unit

Result-centered output

Structured rule, evidence, missingness, and limitation trace

Positive-path feature checks

Trigger, non-trigger, invalid-input, replay, and copy-boundary tests

Platform-dependent ID range

Web-safe random range plus microsecond timestamp

The table reports no accuracy gain because ParkinSUM has no clinical-validation dataset, and more traceable software is not automatically more clinically correct.

The limits remain part of the result

ParkinSUM's mechanistic layer remains an educational simulation. Its gastric-emptying values are literature-informed prototype parameters, and its amino-acid competition layer remains a proxy rather than a patient-specific measurement. The model has not been calibrated against patient pharmacokinetic or outcome data.

The importer adapters are fixture-tested rather than production ingestion pipelines, and public demonstrations use synthetic or sample data. Real-world use would require separate clinical, legal, privacy, security, regulatory, and operational review.

These limits belong inside the engineering story because they define which branches the software may execute and which claims the project may make.

Three lessons generalize

First, validate meaning before evaluating rules because a number without a unit or source is not automatically a usable fact.

Second, store uncertainty as data so provenance, missingness, and confidence survive the pipeline instead of disappearing inside a default value.

Third, treat refusal as a successful output because insufficient_context can be more correct than a detailed score in a high-stakes domain.

The original ParkinSUM question was how to calculate a food–medication conflict. Building the project changed that question: under what conditions is the prototype justified in calculating anything at all?

The most important result is not high, medium, or low. It is the branch that refuses to manufacture precision.

The full source code, model documentation, synthetic replay suite, and verification guide are available on GitHub.

Albert Zhou

Albert Zhou

Passionate developer sharing knowledge about modern web technologies and best practices.

Comments (0)

Login to post a comment.