Phase 3 — Research (Iteration 2)

Phase 3 — Research (Iteration 2)

The central decision: one engine, two granularities

The risk flagged in Review was maintaining two implementations (fast race engine vs. annotated study engine) that could silently diverge. Resolved by unification: a single generator-based micro-stepper is the source of truth.

This was prototyped and validated against the iteration-1 engine as an oracle: across BFS, Dijkstra, Greedy, and A* on three fixtures (weighted, open 15×15, diagonal walls), the generator-driven race produced identical found/visited/cost/steps every time (12/12). The equivalence check is retained as a permanent regression test.

Pseudocode line model (shared skeleton)

Generator yields a state per line id; ids map to the displayed shared-skeleton lines:

line id displayed line per-mode divergence (annotation)
init push start to frontier
pop node ← remove "best" from frontier BFS: oldest · Dijkstra: min g · Greedy: min h · A*: min g+h
goal if node is goal: reconstruct; stop
mark mark node visited
for for each neighbor
skip skip if wall or visited BFS/Greedy also skip if already seen (no re-open)
cost cost ← g[node] + weight(neighbor) BFS ignores weight (orders by steps)
improve if new or cheaper BFS/Greedy: only if unseen
push update g, set parent, push
endExp (loop back to while) race-mode boundary marker
exhausted frontier empty → no path

Each yield carries context: {line, node, neighbor, cost, improved, hit}. The PC walks the same skeleton for all four; the algorithm's real branching (relax vs. first-reach, ordering key) is faithful underneath, while the displayed difference is the annotation + narration. This is precisely the R7 teaching mechanism — the differences live on three lines (pop, cost, improve).

Key technical decisions

Dependencies & security posture

Still zero dependencies. No new external input — only more internal UI state. Pseudocode text, annotations, and narration templates are static strings in code (not user-derived). DOM built via createElement/textContent; no innerHTML/eval. Posture unchanged from iteration 1.

Deferred to Plan