loro Agent Skills & AI Rules

GitHub

Make your JSON data collaborative and version-controlled with CRDTs

RAW Rules
21 Discovered Rules β€’ ~25,940 Estimated Tokens
Quick:
Loading skill content...

AI Agent Protocol & Instructions

AGENTS.md root-instruction ~2,374 tokens
Raw
# Repository Guidelines

## Project Snapshot

Loro is a Rust CRDT workspace with JS/WASM packaging and a MoonBit codec.

- `crates/loro`: public Rust API; avoid breaking downstream users.
- `crates/loro-internal`: core CRDT logic. Read its
  [AGENTS.md](crates/loro-internal/AGENTS.md) before changing import/export,
  encoding, state, diff, checkout, or replay behavior.
- `crates/loro-wasm`: `loro-crdt` WASM/TypeScript package. Read its
  [AGENTS.md](crates/loro-wasm/AGENTS.md) before changing bindings, exports,
  wrappers, or build scripts.
- `crates/delta`, `crates/rle`, `crates/kv-store`, `crates/fractional_index`,
  `crates/loro-common`, and `packages/fractional-index`: shared primitives and
  packages.
- `moon/`: MoonBit Loro binary codec; use [skills/moonbit/SKILL.md](skills/moonbit/SKILL.md).

## Context Index

- Undo/redo item boundaries when remote edits make an inverse a no-op:
  [context/undo-history-boundaries.md](context/undo-history-boundaries.md).
- Rust undo failure rollback and transaction writer serialization:
  [context/undo-atomicity.md](context/undo-atomicity.md).
- Encoding/import/export modes, current vs outdated formats, shallow snapshots:
  [context/internal-encoding.md](context/internal-encoding.md).
- Mergeable container model, marker/cid rules, tests, and common pitfalls:
  [context/mergeable-containers.md](context/mergeable-containers.md).
- `import_batch` force-detach, batch-wide rollback scope, and the never-exit-detached
  invariant: [context/import-batch-atomicity.md](context/import-batch-atomicity.md).
- Which root containers are visible (history-touched vs handle-acquired), and
  why replays materialize empty roots:
  [context/root-container-visibility.md](context/root-container-visibility.md).
- Imports that reuse local op ids (a shared peer id): the known-history check,
  what counts as equal, and what it cannot catch:
  [context/import-peer-id-reuse.md](context/import-peer-id-reuse.md).
- `apply_diff`/`revert_to` rollback of a failed batch, reused op ids, other
  threads: [context/apply-diff-atomicity.md](context/apply-diff-atomicity.md).
- Movable-list `Move`/`Set` import validation, and why a move of a deleted element
  is applied rather than rejected:
  [context/movable-list-op-validation.md](context/movable-list-op-validation.md).
- Shallow-snapshot dead-style redaction (null-only, both-expand exclusion,
  root-whitelisted latest state):
  [context/shallow-snapshot-style-redaction.md](context/shallow-snapshot-style-redaction.md).
- Rich-text insert positions next to style anchors, the insert cursor cache,
  and delete `start_id`s: [context/richtext-insert-positions.md](context/richtext-insert-positions.md).
- Tree diff cache transitions and why their lamport window comes from the two
  versions, not the replay base: [context/tree-checkout-window.md](context/tree-checkout-window.md).
- Tree event invariants (revived subtrees get `Create`s) and the two event
  paths, diff-calculator vs raw ops: [context/tree-events.md](context/tree-events.md).
- Deep tree traversal, snapshot order, and iterative result disposal:
  [context/tree-depth.md](context/tree-depth.md).
- loro.js tree diff item order, index counting, apply resolution, and batch dry-run:
  [context/loro-js-tree-diff.md](context/loro-js-tree-diff.md).
- loro.js concurrent tree moves, skipped cycles, replay, checkout, and undo:
  [context/loro-js-tree-moves.md](context/loro-js-tree-moves.md).
- User-facing Loro usage, sync, editor integration, and performance guidance:
  [skills/loro/SKILL.md](skills/loro/SKILL.md).
- Pure TypeScript runtime indexes, complexity contracts, benchmarks, and remaining gaps:
  [context/loro-js-performance.md](context/loro-js-performance.md).
- loro.js vs Rust randomized Text differential tests and the Rust behaviors they
  work around: [context/loro-js-rust-differential.md](context/loro-js-rust-differential.md).
- loro.js rich-text style anchors, entity positions, and Rust's insert/delete/mark
  position rules: [context/loro-js-richtext-anchors.md](context/loro-js-richtext-anchors.md).
- loro.js multi-peer differential fuzzing against replay, checkout, event, and
  Rust/WASM oracles: [context/loro-js-differential-fuzz.md](context/loro-js-differential-fuzz.md).
- loro.js MovableList model, the MovableList Rust differential suite
  (`loro-js/tests/differential/`), and known loro.js/Rust divergences:
  [context/loro-js-movable-list.md](context/loro-js-movable-list.md).
- WASM panic/OOM reporting channels, `__wbindgen_start` glue invariant, and
  trap-testing recipes:
  [context/wasm-error-reporting.md](context/wasm-error-reporting.md).
- WASM container id wrapper identity, lazy caching, and benchmark:
  [context/wasm-container-id-cache.md](context/wasm-container-id-cache.md).
- Bounded decoded-value cache in `InnerStore` (second-chance FIFO, eviction
  safety contract, loro-dev/loro#1092):
  [context/container-value-cache.md](context/container-value-cache.md).
- Deep plain value decoding, Drop, and WASM conversion stack safety:
  [context/deep-value-stack-safety.md](context/deep-value-stack-safety.md).
- How the arena learns a container's parent (parsed changes, state KV, the op
  log's creator resolver), its locking (including `ChangeStore`'s lock order),
  and import rollback: [context/arena-parent-links.md](context/arena-parent-links.md).
- Why a failed import's rollback keeps arena indices (DocState, caches and handlers
  are keyed by them) and what it drops instead:
  [context/failed-import-arena-indices.md](context/failed-import-arena-indices.md).
- Which deletions `DocState::is_deleted` caches, and how tree/movable-list
  children are revived: [context/dead-container-cache.md](context/dead-container-cache.md).
- Movable-list `apply_diff`/undo: delete + re-insert of a child becomes a move,
  cursor invariant, pitfalls: [context/movable-list-apply-diff.md](context/movable-list-apply-diff.md).
- Unknown container types (newer-version containers): never created locally,
  `apply_diff`/undo pre-check, events, test forging:
  [context/unknown-containers.md](context/unknown-containers.md).
- Why parsed change blocks keep text and list values out of doc-wide arenas
  (`ValueSlice`, tracker tables): [context/text-arena-growth.md](context/text-arena-growth.md).
- User callbacks that panic (subscribers, pre-commit, local updates): no poisoned
  locks, lost events or hangs: [context/callback-panics.md](context/callback-panics.md).
- Context backlog: [context/CONTEXT-GAPS.md](context/CONTEXT-GAPS.md).

## Commands

- JS deps: `pnpm install --frozen-lockfile`.
- Rust build/check/format/lint: `cargo build`, `cargo check -p loro-internal`,
  `cargo fmt --all`, `pnpm check`.
- Rust tests: `pnpm test`; internal doctests: `cargo test -p loro-internal --doc`.
- Loom: `pnpm test-loom`.
- WASM: `pnpm release-wasm`, or `pnpm -C crates/loro-wasm build-dev`.
- Bundlers after WASM packaging changes: `pnpm test-bundlers`; browser runtime:
  `pnpm --dir examples/bundler-smoke-tests run test:browser`.
- Fractional-index TS: `pnpm test-fractional-index`.
- Fuzz smoke: `pnpm run-fuzz-corpus`.
- MoonBit codec, when `moon` is available: from `moon/`, run `moon check`,
  `moon test`, `moon fmt`.

Use narrow checks first. Ask before broad fuzzing or long browser matrices.

## Working Rules

- Start with `git status --short --branch`; treat uncommitted changes as user
  work unless you made them.
- Before editing, read every `AGENTS.md` from root to target directory. Keep
  `CLAUDE.md` as a symlink to the nearest `AGENTS.md`.
- Use `rg` / `rg --files` for search.
- Public API changes in `loro` or `loro-crdt` should be backward-compatible when
  possible. Prefer new `try_*` APIs over breaking signatures.
- Internal corruption should fail fast; invalid external input should return
  `Err`. Returning wrong state is worse than panicking on an impossible internal
  invariant.
- Add regression tests near behavior: `crates/loro/tests`,
  `crates/loro-internal/tests`, module tests, `crates/loro-wasm/tests`, or
  `moon/loro_codec/*_test.mbt`.
- Add a changeset for publishing behavior or package output changes.
- Do not hand-edit generated WASM package output; regenerate it with package
  scripts.

## Self-Maintained Agent Context

- Treat "why was that hard to find?" as a context bug. Add a nearby
  `AGENTS.md` pointer or a `context/` article, or append a line to
  [context/CONTEXT-GAPS.md](context/CONTEXT-GAPS.md).
- Keep root context short. If an `AGENTS.md` grows past about 4000 characters, move
  detail into a linked `context/` article.
- Header context articles with `Verified against code YYYY-MM-DD`, anchor claims
  to files/symbols, and link them from root plus the nearest per-directory
  `AGENTS.md`.
- If code changes make an `AGENTS.md` or context article stale, update the docs
  in the same change.
- When a commit needs non-obvious rationale, land that rationale in the nearest
  context file and keep the commit message as a pointer.

## Commit And PR Notes

History uses short imperative commits, often prefixed by `fix:`, `test:`,
`chore:`, or `refactor:`. PRs should include summary, rationale, validation, and
linked issues or traces when relevant.
- Structured WASM reads, node identity, ranges and performance responsibilities:
  [context/wasm-container-tree.md](context/wasm-container-tree.md).