Agent & Contributor Guide
Relevant source files
The following files were used as context for generating this wiki page:
This guide provides technical specifications and architectural constraints for developers and automated agents contributing to the @b2m9/keyfold library. The project is an immutable state merger designed to fold partial deltas into plain state trees with specialized support for identity-keyed list reconciliation.
Contributors must adhere to strict invariants regarding immutability, structural sharing, and determinism to ensure the library remains a reliable tool for websocket reducers, optimistic UI, and state management.
Sources: AGENTS.md:1-6, README.md:21-25
Development Environment & Toolchain
The project is an ESM-only library requiring Node.js version 22 or higher. It uses a modern TypeScript toolchain with Vitest for testing and Oxlint/Oxfmt for linting and formatting.
| Tool | Purpose | Command |
|---|---|---|
| npm | Package management | npm install |
| TypeScript | Type checking & compilation | npm run typecheck |
| Vitest | Unit & Law testing | npm test |
| Oxlint | Fast linting | npm run lint |
| Oxfmt | Code formatting | npm run format |
| publint/attw | Package/Type validation | npm run check |
Sources: AGENTS.md:8-12, package.json:39-50
Core Architectural Constraints
Every contribution must preserve these library-wide invariants:
- Zero Runtime Dependencies: The library must not ship with any external dependencies.
- Immutability: Neither the
basestate nor thedeltamay be mutated. A failure must not leave partial writes. - Structural Sharing: If a branch is untouched by the delta, the original reference must be retained in the result.
- Determinism: The result must be identical (by reference) if the same valid delta is reapplied.
- Replacement Boundaries: Unkeyed arrays, non-plain objects, and paths explicitly marked for
replaceare swapped wholesale without recursion. - Safe Key Traversal: Merging must ignore internal JavaScript properties like
__proto__,constructor, andprototype.
Sources: AGENTS.md:14-36, src/merge.ts:46-47
Merge Logic Flow
The following diagram illustrates the high-level logic used when folding a delta into a base state:
Sources: src/merge.ts:36-61, src/reconcile.ts:21-50
Path Policy Compilation
Configuration is validated and compiled once during createMerger. This ensures that contradictory or unreachable policies are caught early.
keyBy: Maps a path (e.g.,items) to a field name (e.g.,id).replace: Marks a path for wholesale replacement.- Dead Config Rejection: A
replacepolicy on a parent path makes anykeyBypolicy on a child path unreachable and will cause aKeyfoldConfigError. - Keyed Item Traversal: The segment
[]is used in paths to descend into items of a keyed list.
Sources: src/paths.ts:25-78, README.md:104-118
Policy Node Structure
Policies are stored in a tree structure where each node defines how its level should be handled.
Sources: src/paths.ts:10-19
Reconciliation Logic
Reconciliation is the O(list) exception to delta-proportional work. It involves indexing the delta items and iterating the base items to preserve order.
- Index Delta: Create a Map of identities from the delta list. Duplicate IDs in the delta throw
KeyfoldMergeError. - Process Base: Iterate through the base list.
- If an item's ID is in the delta Map, apply the patch (or remove if
$delete: true). - If not in the Map, keep the original item.
- If an item's ID is in the delta Map, apply the patch (or remove if
- Append New Items: Any items remaining in the delta Map that were not in the base are appended to the end.
- Validation: Check for duplicate IDs in the base list and reserved field usage (like
$deletein base data).
Sources: src/reconcile.ts:21-65, AGENTS.md:28-31
Code Standards & Comments
Contributors should follow specific commenting and coding styles:
- Explain "Why", not "What": Comments should explain the invariant being held or the guard being implemented.
- Present Tense: Use terse, full sentences in the present tense.
- Opaque Values: Instances of
Date,Error,Map,Set,RegExp, and Promises are treated as atomic and replaced rather than merged. - Plain Objects: Only objects with
Object.prototypeornullprototypes are recursed into.
Sources: AGENTS.md:46-52, src/objects.ts:10-16, src/types.ts:63-75
Conclusion
Contributing to @b2m9/keyfold requires a deep understanding of structural sharing and the distinction between recursive merging and wholesale replacement. Agents and developers must ensure that the library remains lightweight, dependency-free, and strictly follows the identity-keyed reconciliation laws defined in the test suite.
Sources: AGENTS.md:14-16, README.md:213-216