Files
ujsx/tasks/value-hash-detection.md
glm-5.1 c9c32a6aa6 decompose reconciler roadmap into 20 implementation tasks across 5 phases
Tasks follow the architecture spec phases:
- Phase 0: key field on UElement (2 tasks + review)
- Phase 1: reactive-host bridge / fiber tree (4 tasks + review)
- Phase 2: key-based children reconciliation (3 tasks + review)
- Phase 3: unmount & dispose support (4 tasks)
- Phase 4: TypeBox value optimizations (4 tasks)

Validated with taskgraph CLI: no cycles, 15 parallel generations,
3 high-risk tasks identified (signal-driven-updates, commit-mutations,
fiber-disposal).
2026-05-18 16:26:52 +00:00

54 lines
2.3 KiB
Markdown

---
id: value-hash-detection
name: Value.Hash O(1) change detection
status: pending
depends_on: [value-clone-prevprops]
created: 2026-05-18T16:22:57.369878873Z
modified: 2026-05-18T16:22:57.369879316Z
scope: narrow
risk: medium
impact: component
level: implementation
---
# Description
Add `Value.Hash` as an O(1) change detection layer before `Value.Equal`. Hash comparison is faster than deep-equal for large subtrees because it's a single integer comparison.
**Critical constraint:** `Value.Hash` uses a global mutable accumulator (FNV-1a state). It is NOT re-entrant. You cannot call `Value.Hash` from within a `computed` or `effect` that is itself triggered by a hash comparison. Hashes must be computed outside reactive computations, during the commit phase.
The optimization strategy from the architecture doc says to add `Value.Hash` after confirming the global accumulator constraint is manageable. This task must verify that the reconciler never calls `Value.Hash` from within a `computed` or `effect`.
Approach:
1. Cache hash on fiber after each commit
2. On next reconciliation, compute hash of new node
3. If hashes differ, proceed to `Value.Equal` check
4. If hashes match, skip subtree (hash match is sufficient for "unchanged")
## Acceptance Criteria
- [ ] `Value.Hash` imported from `@alkdev/typebox/value`
- [ ] Fiber caches hash value after each commit (new `hash` field)
- [ ] On reconciliation: hash comparison before `Value.Equal` comparison
- [ ] Hash computed OUTSIDE reactive computations (commit phase only)
- [ ] Verified: no `Value.Hash` call happens inside `computed` or `effect` callbacks
- [ ] When hashes differ, falls through to `Value.Equal` (then to full reconciliation)
- [ ] When hashes match, skip subtree (fast path)
- [ ] Existing tests pass
- [ ] New test: unchanged subtree detected by hash match
- [ ] New test: hash mismatch falls through to Value.Equal / reconciliation
- [ ] New test: hash never called from within a computed/effect
## References
- docs/architecture/reconciler.md — TypeBox Optimization Layer, Value.Hash row, Value.Hash Constraint
- docs/architecture/reconciler.md — Optimization Strategy (step 2)
- docs/architecture/reconciler.md — Open Question 3 (should Value.Hash be used given the constraint)
## Notes
> To be filled by implementation agent
## Summary
> To be filled on completion