HOMURAJS v1.5.1
WP PLUGIN GITHUB NPM
SPEC // 01.0
SYS_REV // 1.5.1
WP_PLUGIN // v1.5.1
ENGINE // DAG_PROXY
STATUS // PRODUCTION_HARDENED
NEW: HomuraJS v1.5.1 — frozen history, real QR handoff, sessionStorage drafts & async middleware →

The Directed Acyclic Graph State Engine for JavaScript.

Conventional state managers treat history as a flat stack. When you undo and mutate, future steps are permanently destroyed. HomuraJS forks non-destructive timeline branches — Git for application state.

npm install @biagioscaglia/homurajs
LIVE RUNTIME CONSOLE
Active Node: "Initialized"
SPEC // 01.1 // CORE_PROBLEM

The Fundamental Flaw of Linear History

Every standard undo/redo implementation (from Redux-Undo to naive history arrays) uses a 1D linear stack. This model creates silent, permanent data loss during real-world user interaction:

TRADITIONAL LINEAR STACK DESTRUCTIVE
Action A ──> Action B ──> Action C (Head) │ └── [User steps back 2x to Action A] │ └── [User performs Action D] │ [X] Action B and Action C are PERMANENTLY DESTROYED.

Because linear arrays have only one future pointer, applying any change from a previous state truncates everything ahead.

HOMURAJS DIRECTED ACYCLIC GRAPH NON-DESTRUCTIVE
State A ──> State B ──> State C (main branch) │ └── [User rewinds to State A and mutates] │ ├──> State D ──> State E (experimental branch) │ [OK] Both branches coexist, are navigable, and can be merged.

Every mutation creates a new node in the Directed Acyclic Graph. Branch divergence preserves 100% of historical states forever.

SPEC // 01.2 // GRAPH_THEORY

Directed Acyclic Graph (DAG) Topology

Each state in HomuraJS is an immutable node containing state snapshots, parent-child links, timestamps, and semantic metadata:

packages/core/src/types.ts
export interface HistoryEntry<T> {
  id: string;              // UUIDv4 node identifier
  parentId: string | null; // Direct ancestor pointer
  childrenIds: string[];   // Successor branches (forks)
  branchId: string;        // Active timeline branch
  timestamp: number;       // Unix epoch ms
  label: string;           // Semantic operation descriptor
  state: T;                // Frozen immutable snapshot
  metadata?: Record<string, unknown>;
}
SPEC // 02.0 // DEPLOYMENT

Package Installation

Install the unified meta-package or individual modular packages according to your project requirements:

npm install @biagioscaglia/homurajs
SPEC // 02.1 // RUNTIME_INIT

Quick Start Specification

Initialize the engine, perform mutations via Copy-On-Write draft proxies, and execute non-destructive time travel:

example.ts
import { createHomura } from '@biagioscaglia/homurajs';

interface AppState {
  counter: number;
  user: { name: string; role: string };
}

const homura = createHomura<AppState>({
  initialState: {
    counter: 0,
    user: { name: 'Homura', role: 'Architect' }
  }
});

// Mutate via Copy-On-Write Proxy Draft
homura.update(draft => {
  draft.counter += 10;
  draft.user.role = 'Lead';
}, { label: 'Promote user and increment' });

// Non-destructive Time Travel
homura.undo(); // State reverts to counter: 0
homura.redo(); // State returns to counter: 10

// Branching
homura.createBranch('experimental');
homura.update(draft => { draft.counter = 999; });
SPEC // 02.2 // MODULE_ANATOMY

Monorepo Package Architecture

Package Bundle Size Role & Capabilities
@homura-js/core < 5.2 kB Core DAG graph engine, Proxy draft immutability, structural diffing, snapshot registry, persistence.
@homura-js/devtools < 9.4 kB Standalone diagnostic GUI: visual timeline tree, JSON state tree inspector, side-by-side diff viewer.
@homura-js/vanilla < 2.8 kB Reactive DOM binding (bindState) and Zero-JS form auto-binding crash recovery (bindForm).
@homura-js/react < 2.1 kB React 18+ bindings with useSyncExternalStore and selector optimization.
@homura-js/vue < 2.3 kB Vue 3 Composition API hook (useHomura) and plugin wrapper.
@biagioscaglia/homurajs Meta Unified meta-package + standalone browser CDN bundle (dist/index.global.js).
SPEC // 02.3 // MEMORY_MODEL

Copy-On-Write Proxy Immutability

HomuraJS intercepts state writes using JavaScript Proxies. Mutations are isolated in a temporary draft and applied with structural sharing:

Published snapshots are deep-frozen: mutating getState() throws. Use update(..., { silent: true }) for in-place edits without a history node, and setStateAsync when middleware returns a Promise.

atomic-transactions.ts
// Atomic Transactions: Multiple operations collapsed into a single DAG node
homura.transaction(draft => {
  draft.counter += 50;
  draft.user.name = 'Madoka';
  draft.user.role = 'Guardian';
}, { label: 'Atomic Profile Update' });
SPEC // 02.4 // STRUCTURAL_DIFF

Structural Diff Engine & Replay

Calculate recursive JSON difference sets between any two nodes in the DAG with exact dot-paths and types:

diff-engine.ts
const diffs = homura.diff('entry-node-a', 'entry-node-b');
// Returns:
// [
//   { type: 'modified', path: 'user.role', oldValue: 'Architect', newValue: 'Lead' },
//   { type: 'added', path: 'flags.experimental', newValue: true }
// ]
SPEC // 03.1 // ZERO_JS_FORMS

Vanilla JS & Zero-JS Static Site Form Engine

Turn any static HTML form (Webflow, Shopify, Squarespace, Static HTML) into a time-travel crash-recovery machine without writing JavaScript:

static-form.html
<!-- CDN Standalone Script -->
<script src="https://unpkg.com/@biagioscaglia/homurajs/dist/index.global.js"></script>

<!-- Declarative Auto-Bound Form -->
<form data-homura-form="lead_capture" data-homura-persist="localstorage">
  <span data-homura-status></span>
  <div data-homura-breadcrumbs></div>

  <input type="text" name="name" placeholder="Full Name" />
  <input type="email" name="email" placeholder="Email Address" />
  <textarea name="specifications"></textarea>

  <button type="button" data-homura-undo>Undo</button>
  <button type="button" data-homura-redo>Redo</button>
  <button type="submit">Submit Form</button>
</form>

Multi-Step Form Wizard (data-homura-wizard)

wizard.html
<form data-homura-wizard="quote_wizard" data-homura-persist="localstorage">
  <div data-homura-step="1">
    <label>Step 1: Budget</label>
    <input type="number" name="budget" />
    <button type="button" data-homura-next>Next Step</button>
  </div>
  <div data-homura-step="2">
    <label>Step 2: Contact</label>
    <input type="email" name="email" />
    <button type="button" data-homura-prev>Back</button>
    <button type="submit" data-homura-next data-submit-label="Finish">Submit</button>
  </div>
</form>
SPEC // 03.2 // PHP_WORDPRESS

WordPress & WooCommerce Integration

Homura Time Travel & Form Recovery Official Plugin on WordPress.org (v1.5.1)
View on WordPress.org Plugin Directory

Install directly from WordPress Admin via Plugins → Add New → Search "Homura Time Travel", or download from WordPress.org:

The official HomuraJS WordPress plugin brings DAG state history, checkout recovery, and form crash protection to WordPress & WooCommerce forms with zero configuration:

WordPress Shortcode Implementation (v1.5.1)
[homura_form id="lead_quote" persist="localstorage" crypto="aes-gcm"]
  [homura_status form="lead_quote"]
  [homura_breadcrumbs form="lead_quote"]
  [homura_ghost_assist form="lead_quote"]

  <input type="text" name="company" placeholder="Company Name" />
  <textarea name="project_scope" placeholder="Describe scope..."></textarea>

  [homura_undo form="lead_quote" label="Undo"]
  [homura_redo form="lead_quote" label="Redo"]
  [homura_handoff form="lead_quote" label="📱 Continue on Mobile"]
  [homura_visual_diff form="lead_quote" field="project_scope" label="📝 Visual Diff"]
  [homura_clear form="lead_quote" label="Clear Draft"]
[/homura_form]

Automatic Hooks for Top Form Engines

The plugin auto-detects and attaches crash recovery to:

  • WooCommerce Checkout (.woocommerce-checkout)
  • Contact Form 7 (.wpcf7 form)
  • WPForms & Gravity Forms (.wpforms-form, .gform_wrapper)
  • Elementor Forms, Fluent Forms & Ninja Forms
SPEC // 03.3 // REACT_BINDING

React 18+ Integration (@homura-js/react)

UserDashboard.tsx
import React from 'react';
import { useHomura } from '@homura-js/react';
import { homura } from './store';

export function UserDashboard() {
  const { state: user, update, undo, redo, canUndo, canRedo } = useHomura(
    homura,
    s => s.user
  );

  return (
    <div>
      <h3>User: {user.name}</h3>
      <button onClick={() => update(d => { d.user.name = 'New Name'; })}>Update</button>
      <button disabled={!canUndo} onClick={() => undo()}>Undo</button>
      <button disabled={!canRedo} onClick={() => redo()}>Redo</button>
    </div>
  );
}
SPEC // 03.4 // VUE_BINDING

Vue 3 Composition API (@homura-js/vue)

Counter.vue
<template>
  <div>
    <h3>Counter: {{ state.counter }}</h3>
    <button @click="increment">+1</button>
    <button :disabled="!canUndo" @click="undo">Undo</button>
    <button :disabled="!canRedo" @click="redo">Redo</button>
  </div>
</template>

<script setup lang="ts">
import { useHomura } from '@homura-js/vue';
import { homura } from './store';

const { state, update, undo, redo, canUndo, canRedo } = useHomura(homura);

function increment() {
  update(d => { d.counter++; }, { label: 'Increment' });
}
</script>
SPEC // 03.5 // DEVTOOLS_GUI

Embedded Diagnostic DevTools & Visual Time Machine

Zero-dependency diagnostic panel with interactive DAG visual tree, keyboard navigation (←/→/Space), speed controls, drag-and-drop .homura session replay, and diff scrubber:

devtools-mount.ts
import { mountDevTools } from '@homura-js/devtools';

// Mount interactive Visual Time Machine
mountDevTools(homura, {
  position: 'floating', // 'floating' | 'embedded'
  theme: 'dark',
  defaultOpen: true
});

// Keyboard Navigation Active:
// [← / Undo]  [→ / Redo]  [Space / Play-Pause]  [Home / Rewind]  [End / Latest]

Web Worker Off-Thread Async Diffing Engine

Compute massive state differences without blocking the UI thread (120 FPS guaranteed) using Web Worker async diffing with zero separate assets and automatic Node/SSR fallback:

async-diff-worker.ts
import { diffStatesAsync, createAsyncDiffer } from '@biagioscaglia/homurajs';

// Offload heavy structural diffing to background Web Worker thread
const changes = await diffStatesAsync(largeDataSetA, largeDataSetB, {
  timeoutMs: 3000
});

console.log('Detected diffs off-thread:', changes);
SPEC // 03.6 // FORENSIC_TOOLING

Forensic Bug Reporting & Session Playback (.homura)

Debug application state like you debug source code. Export entire DAG timelines from production or QA sessions and replay them step-by-step on any developer machine:

forensic-debugging.ts
// 1. Client / User encounters an unexpected bug in production
window.addEventListener('error', () => {
  // Capture 100% of the DAG state evolution up to the moment of failure
  const sessionData = homura.export();
  sendErrorReport('crash-session.homura', sessionData);
});

// 2. Developer imports the session in DevTools or local environment
homura.import(crashSessionData);

// 3. Replay the exact sequence of user actions that corrupted the state
await homura.replay({
  speed: 2,
  onStep: (entry, step, total) => {
    console.log(`[Step ${step}/${total}] Transition: ${entry.label}`, entry.state);
  }
});
// 4. Jump directly to the failing node and compute the recursive structural diff
  homura.jumpTo('corrupted-node-id');
  const diffs = homura.diff('previous-valid-node', 'corrupted-node-id');
SPEC // 03.7 // DATABASE_FORENSICS

HomuraDB & Full-Stack State Correlation (@homura-js/db)

Version your database state

Record table inserts, updates, and deletes as an immutable Directed Acyclic Graph (DAG) on top of embedded SQLite or memory stores with instant time-travel and branch merging.

Full-Stack State Correlation

Connect UI state (#184), network requests, and database transactions (#52) into one reproducible causal history exported as a unified .homura forensic session:

fullstack-correlation.ts
import { createHomuraDB, createForensicRecorder } from '@homura-js/db';

// 1. Initialize Versioned Database Engine (Embedded SQLite / Memory)
const db = createHomuraDB({ name: 'production_store' });
db.createTable('orders');
db.createTable('inventory');

// 2. Attach Full-Stack Forensic Recorder
const recorder = createForensicRecorder({
  clientHomura, // Frontend UI Homura State (#184)
  db            // Backend Database HomuraDB State (#52)
});

// 3. Correlate HTTP Network Requests with Database Mutations
recorder.recordNetworkTrace({
  url: '/api/checkout',
  method: 'POST',
  statusCode: 200,
  requestBody: { cart: ['cyber_shield_01'] }
});

db.transaction(tx => {
  tx.insert('orders', { id: 'ord_99', total: 250, status: 'confirmed' });
  tx.update('inventory', 'SHIELD-01', { stock: 48 });
}, {
  label: 'Atomic Checkout Transaction',
  clientStateId: clientHomura.getCurrentEntry().id
});

// 4. Export Unified Forensic Session (.homura)
const sessionJSON = recorder.exportJSON();
// sessionJSON contains: Client UI DAG + Network Trace Timeline + Database Mutation DAG
SPEC // 04.0 // ARCHITECTURAL_COMPARISON

Architectural Scope & Paradigm Comparison

Understanding how HomuraJS state history infrastructure compares to focused single-purpose libraries across different layers of the JavaScript stack:

Paradigm / Scope HomuraJS Redux-Undo Zustand History XState Immer
Primary Design Target State History Infrastructure Redux Store Enhancer Zustand Middleware State Machine Orchestration Immutability Utility
History Model Directed Acyclic Graph (DAG) 1D Linear Stack (Past/Future) 1D Linear Stack (Temporal) Transition Graph / Statechart N/A (Copy-on-Write Proxy)
Branching & 3-Way Merge Built-in (Non-destructive) Destructive on new action Destructive on new action Parallel State Nodes N/A
Full-Stack Forensics (.homura) UI ↔ Network ↔ DB Correlation N/A (Client Redux only) N/A (Client Store only) Event Inspection Protocol N/A
Zero-JS Static & WordPress Forms Auto-Recovery & WP Plugin N/A N/A N/A N/A
Structural Diffing Engine Recursive Dot-Path Engine N/A N/A N/A JSON Patches (RFC 6902)
Diagnostic GUI & Replay Embedded Visual DevTools Browser Extension / Redux DevTools N/A XState Stately Visualizer N/A
Runtime Dependencies Zero Dependencies Requires Redux Requires Zustand Zero Dependencies Zero Dependencies
SPEC // 04.1 // API_MATRIX

Complete Homura<T> API Matrix

Method Signature Return Type Description
getState() T Returns the current deep-frozen immutable snapshot (mutations throw).
update(updater, options?) HistoryEntry<T> Mutates via Copy-On-Write draft. Supports silent: true (in-place, no history node) and skips no-op drafts.
setState(state, options?) HistoryEntry<T> Replaces state synchronously through the middleware pipeline.
setStateAsync(state, options?) Promise<HistoryEntry<T>> Await async middleware before committing a replacement state.
undo() HistoryEntry<T> | null Steps back to parent entry in DAG.
redo() HistoryEntry<T> | null Steps forward to next child entry on branch.
canUndo() / canRedo() boolean Returns boolean availability of undo/redo actions.
transaction(fn, options?) HistoryEntry<T> Batches multiple operations into a single atomic history node.
createBranch(name, fromEntryId?) Branch Forks an alternative timeline branch from any node.
merge(sourceBranchId, options?) HistoryEntry<T> Merges a branch into the active branch (3-way, fast-forward, or custom resolver).
diff(entryA, entryB?) DiffChange[] Deep structural dot-path diffing between two states.
snapshot(name?, metadata?) Snapshot<T> Creates a named milestone bookmark at active node.
replay(options?) Promise<void> Automated step-by-step timeline playback.
SPEC // 04.2 // BENCHMARKS

Engine Performance Specs

Operation Throughput Latency (10,000 Nodes)
Node Mutation (Proxy Commit) ~185,000 ops/sec 0.005 ms
DAG Timeline Jump (Rewind/Fast-Forward) ~420,000 ops/sec 0.002 ms
Deep Structural Diff (Nested 500 keys) ~95,000 ops/sec 0.010 ms
State Serialization (export/import) ~45,000 ops/sec 0.022 ms
🔬 Benchmark Methodology & Complexity Profile
  • O(1) Hash Map Timeline Jump (~0.002 ms): Homura indexes all DAG entries in a flat dictionary by UUID. Jumping to any node resolves in O(1) time directly without replaying intermediate node deltas.
  • Proxy Mutation (~0.005 ms): Copy-On-Write drafts clone only modified dictionary branches, sharing memory references for unmodified subtrees.
  • Dataset Size: Tested across 10,000 active nodes and 500 deep nested object properties per state.

All performance metrics are fully reproducible. Run the benchmark suite on your local machine:

git clone https://github.com/biagio-scaglia/homura-js.git
cd homura-js && pnpm install
pnpm run bench
SPEC // 04.3 // FREQUENT_QUESTIONS

Frequently Asked Questions

How does HomuraJS prevent memory leaks with large DAG histories?

HomuraJS uses Copy-On-Write structural sharing: unmodified parts of the state tree share memory references across all nodes. Additionally, compact() and pruneHistory() allow pruning redundant linear steps while preserving named snapshots and branch junctions.

Can HomuraJS be used without React or Vue?

Yes. @homura-js/core has zero dependencies. You can use it in Vanilla JS, Node.js, Svelte, Solid, Angular, or in static HTML/WordPress sites via @homura-js/vanilla or shortcodes.

How does HomuraJS protect WooCommerce checkout & WordPress forms?

The official WordPress plugin auto-hooks into .woocommerce-checkout, .wpcf7, .wpforms-form, .gform_wrapper, and .elementor-form, saving input to LocalStorage or SessionStorage in real-time. Real QR handoff, Ghost Assist, and WooCommerce AJAX recovery restore drafts after crash, refresh, or cart recalculation.

Can HomuraJS be used on static sites without npm (CDN)?

Yes. Include unpkg.com/@biagioscaglia/homurajs/dist/index.global.js via script tag and declare data-homura-form="form_id" data-homura-persist="localstorage" or "sessionstorage" on your HTML forms.

Is published state frozen, and how do I use async middleware?

Yes. getState() returns a deep-frozen snapshot. Use update(..., { silent: true }) for in-place changes without a history node, and setStateAsync when middleware returns a Promise.