Duende Builder feature guide

Candidate Difference Explanation

How planners understand changed scheduled work without changing plan authority

Candidate Difference Explanation: Business And Architecture Guide

Status: engineering complete and merged through PR #33; Mike product-owner acceptance remains pending

Date: 2026-07-14

Baseline: RH Scheduler v9.346 at current-main source commit a618d8ce995fbcea4c5c8685374fe1feb94e96da, with merged F1 saved-candidate browsing, plus the final F2 matching-rule copy correction identified during closeout review

Document owner: Kalen Howell Sr.

Audience: Mike, schedulers, product reviewers, developers, and maintainers

One-Minute Explanation

F1 lets a scheduler reopen saved optimizer candidates. F2 makes those saved results useful for a decision by answering a more practical question: what scheduled work changed?

The scheduler compares the latest review-only candidate with a selected prior candidate. It still shows the evidence fingerprints, scheduled-row counts, and warning totals, but it now adds a plain-language work summary. The summary shows work that was added, removed, changed, unchanged, or too ambiguous to match safely. When two rows can be matched, it can explain changes to the scheduled date, pour station, mix tank, operator, quantity, labor hours, late status, and conflict state.

Authority boundary: comparison explains saved evidence only. It does not rerun the optimizer, edit either candidate, change the current schedule, approve a plan, release work to the floor, or make a customer commitment.

Business Problem And Value

Before

The existing comparison could tell Mike that an output fingerprint or row count changed, but it could not identify the affected work. He had to open separate outputs and manually search for the difference.

That left the important operating questions unanswered:

  • Which orders or production tasks moved?
  • Did work change days, stations, tanks, or operators?
  • Was work added or removed?
  • Did labor hours, late status, or a conflict change?
  • Is the apparent match trustworthy, or does it need manual review?

After

The comparison now translates stored schedule rows into operational differences. Mike can see a compact summary, then open the changed-work detail to inspect the exact fields that differ.

For example:

Candidate PC-000014 compared with PC-000013

Changed: 1    Added: 0    Removed: 0    Unchanged: 4    Needs review: 0

Order 4215 - HH-66 Vinyl Cement - 128 oz
Scheduled date: 2026-07-14 -> 2026-07-15
Pour station: Scale 1 (PS-2) -> Scale 2 (PS-3)
Mix tank: Tank 4 -> Tank 6
Primary operator: Alex -> Jordan

This explanation does not say which candidate is better. It gives the planner the evidence needed to make that judgment.

Product Value

Value Browser-proven behavior Practical result
Faster review Work-level counts and details appear below the aggregate comparison Mike does not have to manually scan two full schedules
Operational language The view names orders, dates, stations, tanks, operators, quantities, hours, late status, and conflicts when present The difference is understandable without reading JSON or fingerprints
Safer uncertainty Duplicate or incomplete identities are labeled for manual review The product does not silently pair unrelated work
Preserved authority Both candidates remain visibly not released and comparison performs no writes Reviewing alternatives cannot alter the floor schedule

People And Workflow

The primary user is the scheduler reviewing optimizer alternatives. The input is two saved PlanCandidate records: the latest candidate and one selected prior candidate. The output is a read-only explanation. The decision remains with the scheduler or product owner.

Business flow showing a planner selecting a prior candidate, reviewing aggregate and work-level differences, resolving ambiguity manually, and stopping before any release action

How to read this view: Blue steps are implemented comparison behavior. Amber marks an ambiguity that needs a person. The red stop makes clear that F2 never crosses into plan approval or release.

Mike-Facing Demonstration

  1. Open the Order Optimizer with fictional saved candidates.
  2. Compare the latest candidate with a prior candidate.
  3. Read the summary counts for changed, added, removed, unchanged, and ambiguous work.
  4. Open changed work and identify the affected order and fields.
  5. Review an ambiguous example and confirm that the product refuses to invent a match.
  6. Reload and repeat the comparison.
  7. Confirm that candidate history and the current schedule are unchanged.

Feature Behavior

Comparison Levels

The supplied product explanation described four useful levels. F2 implements the parts supported by the current saved candidate data:

  1. Executive summary: changed, added, removed, unchanged, and needs-review counts, alongside the existing row and warning totals.
  2. Operational summary: schedule date, station, tank, operator, quantity, labor-hours, late-status, and conflict changes when those fields exist.
  3. Order-level detail: the affected order, product, size, and customer label for each safely identified work row.
  4. Exception summary: ambiguous matches are separated for manual review; existing warning-type deltas remain available.

Delivery assignments, total overtime, utilization percentages, and batch-plan comparisons are not consistently stored in the candidate outputSnapshot. F2 does not infer those facts from unrelated live state.

Deterministic Work Identity

F2 may compare changing schedule attributes only after it identifies the same underlying work in both snapshots. The identity uses stable fields already present on v9.346 output rows:

  • order ID;
  • adhesive or task product;
  • size;
  • task type;
  • channel; and
  • stock destination when applicable.

Scheduled date, station, tank, operator, quantity, hours, late status, and conflict are deliberately excluded from identity because those are the fields the user needs to compare.

If an identity is missing or appears more than once in either snapshot, the rows are labeled Needs manual review. They are not paired automatically.

Failure And Boundary States

  • A candidate without a readable outputSnapshot produces a specific visible limitation.
  • A missing candidate or a candidate with a released status produces the existing safe comparison error.
  • Duplicate identities are reported as ambiguous, including the number of rows found on each side.
  • Rows without an order ID or product identity are reported as unresolved.
  • All restored labels and values are HTML-encoded before display.
  • Comparison writes neither rha_planCandidates nor rha_scheduled.

Deliberate Non-Goals

F2 does not:

  • approve, release, select, or edit a plan;
  • recommend which candidate Mike should choose;
  • rerun optimization or explain the optimizer's causal reasoning;
  • compare two arbitrary non-latest candidates in the current UI;
  • compare a candidate with production actuals or a released plan;
  • calculate delivery moves, overtime percentage, utilization, or financial impact from data that is not stored in the candidate snapshot; or
  • synchronize candidate history across browsers or users.

System And Runtime View

Runtime sequence showing read-only candidate loading, deterministic identity grouping, safe work comparison, ambiguity handling, encoded rendering, and no writes

How to read this view: The scheduler reads two local candidates. The pure comparison functions group rows by stable identity and either explain a safe match or return an ambiguity. The UI encodes all displayed values. The local candidate store and current schedule receive no writes.

Runtime Steps

  1. readPlanCandidateStore loads the local append-only candidate list.
  2. renderPlanCandidateComparison selects the latest and requested prior candidate.
  3. comparePlanCandidates preserves the aggregate fingerprint, row, and warning comparison.
  4. comparePlanCandidateWork validates both snapshots and groups rows by the deterministic identity from getPlanCandidateWorkIdentity.
  5. Unique matches are summarized by summarizePlanCandidateWorkRow; display fields are compared one by one.
  6. Missing or duplicate identities become ambiguity records rather than guessed matches.
  7. renderPlanCandidateComparison HTML-encodes every restored label and value and presents the work summary below the aggregate evidence.

Technical Implementation

Business concept Implementation Practical meaning
Stable work identity getPlanCandidateWorkIdentity Match only source-backed order/product/task fields
Operational row summary summarizePlanCandidateWorkRow Translate a schedule row into planner-facing labels and values
Pure changed-work engine comparePlanCandidateWork Classify added, removed, changed, unchanged, and ambiguous work without writes
Aggregate plus work comparison comparePlanCandidates Keep earlier evidence deltas and add the work explanation
Visible comparison renderPlanCandidateComparison Show encoded summaries, details, ambiguity, and nonrelease labels
Focused contract tests plan-candidate-work-differences.test.mjs Prove matching, changes, ambiguity, limitations, encoding, and no writes

All runtime implementation remains inside src/prototype/rh_adhesives_scheduler_0346.html, consistent with the accepted prototype baseline. The pure comparison functions create a bounded seam that can move into the Phase 1 modular local application later without changing the user contract.

Data, Security, And Operations

Candidate history remains local to one browser profile in the rha_planCandidates record. F2 reads the full saved outputSnapshot; it does not add another persistence format. The current schedule remains in rha_scheduled and is outside comparison authority.

Backup and restore can introduce strings that did not originate in the current UI. Candidate IDs, customer names, products, operators, stations, conflicts, and every other restored value are therefore treated as untrusted display data and encoded before insertion into HTML.

This is local Phase 1 behavior. It does not provide server authentication, shared cloud state, authorization, audit, migration, or production deployment.

Decisions, Risks, And Future Possibilities

Decisions Made In F2

  • Safety is preferred over a visually plausible match.
  • Identity excludes the schedule fields that the planner needs to compare.
  • The latest candidate remains one side of the comparison in the current UI.
  • The product explains differences but does not rank or accept candidates.
  • Facts not stored in candidate snapshots are not inferred from live state.

Remaining Risks

  • A legitimate order line split into multiple rows can become ambiguous. This is intentional until the modular application introduces a durable plan-line identifier.
  • Snapshot fields reflect optimizer output, not production actuals.
  • Candidate history remains local to one browser and can be lost without a valid backup.
  • The comparison is useful evidence, not proof that either plan is feasible or approved.

Reusable Direction After Phase 1

The product explanation also identified valuable later comparisons:

  • current candidate versus released plan;
  • today's plan versus yesterday's plan;
  • optimizer version versus optimizer version;
  • planned production versus actual production; and
  • a causal explanation of why the optimizer recommended a change.

Those uses can reuse the same read-only comparison posture, but they need Phase 2 authority, persistence, identity, and actuals contracts. They are not claimed as delivered by F2.

Verification

The implementation requires:

  • focused RED/GREEN tests for unchanged, added, removed, changed, ambiguous, and missing-snapshot behavior;
  • regression coverage for aggregate comparison, history, traceability, warning compatibility, and restored-value encoding;
  • full repository validation and scheduler syntax checks;
  • a real-browser demonstration with fictional candidates; and
  • before/after proof that rha_planCandidates and rha_scheduled did not change during comparison.

F2 Acceptance Receipt

  • Browser baseline: RH Scheduler v9.346 served locally in headed Chromium from the isolated F2 worktree.
  • Fictional scenario: the latest and prior candidates produced one changed order, one added order, one removed order, and one duplicated identity that required manual review.
  • Observed explanation: the changed order showed scheduled date, station, tank, primary and additional operators, quantity, labor hours, late status, and conflict changes. Added and removed details opened independently.
  • Safety behavior: the duplicate identity was not paired. Removing the prior snapshot produced the specific unreadable-snapshot limitation.
  • Reload behavior: reloading preserved candidate history and reproduced the same comparison.
  • Authority evidence: comparison retained candidate IDs PC-000001 and PC-000002, kept nextSequence at 3, and left rha_scheduled as [].
  • Known browser noise: the prototype's existing malformed embedded-logo data URL and missing favicon produced two resource errors; no F2 runtime error appeared.

Engineering completion, merge, and Mike's product acceptance remain separate lifecycle states. Mike acceptance is not required to continue the next engineering lane, but it is required for Phase 1 product acceptance.

Current-Main Closeout Verification

The F2 comparison seam is unchanged from the PR #33 merge. On 2026-07-14 it was reverified against the newer current-main scheduler source at a618d8ce995fbcea4c5c8685374fe1feb94e96da:

  • all four focused candidate suites passed, 26 tests total, including a table-driven contract proving each of the six source-backed identity fields prevents silent pairing when it differs;
  • a headless Google Chrome run showed 2 changed, 1 added, 1 removed, 1 unchanged, and 3 needs-review outcomes from fictional rows;
  • duplicate identity and one incomplete identity on each side remained unresolved for manual review;
  • the fully recorded match explained date, station, tank, operators, quantity, labor hours, late status, and conflict, while a sparse match explained only its recorded date change;
  • restored markup-like customer and operator values stayed visible as encoded text, with zero injected img, svg, or script elements;
  • warning types named __proto__ and constructor remained countable and visible;
  • repeated rendering and a full reload left the 4,969-byte candidate-history value and 155-byte current-schedule value byte-equivalent; and
  • the browser-fetched source was byte-identical to the integrated worktree prototype: 1,535,115 bytes with SHA-256 3c2e077e60fb05c6890586140bca861faff68754f86bf723bdb1f7a0c3e8b8b7.

The browser reported only the prototype's known malformed embedded-logo data URL. No F2 runtime error appeared. Final review found that the visible matching rule omitted stock destination even though the deterministic identity included it; the footer was corrected without changing scheduling or comparison logic.

Current-main browser evidence Value
Captured 2026-07-14
Browser viewport Headless Google Chrome, 1200 x 1279 pixels
Acceptance scenario P1-A06: browse prior candidates and explain affected scheduled work without inventing ambiguous matches
Data classification Fictional test data; no private RH data
Authority proof Candidate history and rha_scheduled remained byte-equivalent through comparison and reload

Portfolio Evidence

The following screenshots were captured from the real locally running v9.346 scheduler using fictional candidate data. They are product evidence, not a mockup or reconstructed design.

Candidate comparison showing changed, added, removed, unchanged, and needs-review work with operational field details

Comparison result: Mike can see the affected scheduled work, expand each classification, and identify ambiguous rows that the product refuses to match automatically. Both candidates remain visibly review-only and not released.

Candidate comparison boundary showing a specific unreadable-snapshot error while saved history remains unchanged

Safe failure boundary: a prior candidate without a readable scheduled-work snapshot produces a specific limitation instead of a false comparison result.

Evidence metadata Value
Feature F2 / candidate-difference-explanation
Captured 2026-07-13
Tested merge dc29c885beb97ad4ccaa063da1bac42b5ff77fc8
Feature commit 44c24f40b0d425f0f78c6661b9e1bf373e859ae8
Browser viewport 1440 x 1000
Acceptance scenario P1-A06
Data classification Fictional test data; no private RH data
Authority proof Comparison remained read-only; candidate history and rha_scheduled were unchanged

The 2026-07-14 closeout run used the separately recorded 1200 x 1279 headless Google Chrome viewport and fictional data. Its exact source baseline and byte-equivalence results are recorded above; the controller will attach the final documentation-lane SHA and independent review evidence during merge closeout.

Glossary

Term Plain meaning
Candidate A saved optimizer result under review; not an official production plan
Aggregate evidence Fingerprints, row totals, warning totals, and warning-type counts
Output snapshot The scheduled rows saved with one candidate
Work identity Stable order/product/task fields used to decide whether two rows may be compared
Changed work One safely matched task whose operational display fields differ
Added work A unique work identity found only in the latest candidate
Removed work A unique work identity found only in the prior candidate
Ambiguous work Rows the product refuses to pair because identity is missing or duplicated
Nonreleased Review-only; not approved or authorized for the production floor

Source Trail

  • F2 Feature Explanation supplied by Kalen
  • docs/requirements/features/2026-07-12-plan-candidate-difference-brief.md
  • docs/requirements/features/2026-07-12-plan-candidate-history-brief.md
  • docs/requirements/phase-1-core-feature-roadmap.md
  • src/prototype/rh_adhesives_scheduler_0346.html
  • tests/scheduler/plan-candidate-work-differences.test.mjs
  • tests/scheduler/plan-candidate-comparison.test.mjs
  • tests/scheduler/plan-candidate-history.test.mjs
  • tests/scheduler/plan-candidate-traceability.test.mjs

The supplied conversation established the user-centered product framing. The repository brief and v9.346 source determine which parts are implemented now and which remain future possibilities.

Maintenance Note

Update this guide, its diagrams, and generated standalone HTML when candidate identity, comparison fields, ambiguity behavior, persistence, authority, or the Mike-facing workflow changes.