Instead of bailing when children have duplicate filesystem names,
syncback now resolves collisions by appending incrementing suffixes
(e.g. Foo, Foo1, Foo2). This handles both init-renamed children and
any other name collisions. Meta stem derivation is now path-based
to correctly handle collision suffixes and dotted names.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Drop the strip_suffix(extension) approach for computing adjacent meta
file names. Instead, use the instance name directly (slugified if it
has invalid filesystem chars, prefixed with '_' if it's "init"). This
is the same logic as the original code plus init-prefix handling, and
correctly preserves dots in instance names like "Name.new".
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Two bugs:
1. Meta stem fallback used raw instance name (unslugged), so names with
forbidden chars like '/' would create bogus directory components in
the meta path. Fix: fallback now slugifies + init-prefixes, matching
name_for_inst.
2. AdjacentMetadata name check used split('.').next() to extract the
filesystem stem, breaking dotted names like "Name.new" (stem became
"Name", mismatched the instance name, wrote an unnecessary name
property). Fix: check the conditions that cause name_for_inst to
diverge (invalid chars or init-prefix) directly instead of comparing
path stems.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The previous fix used split('.').next() to get the meta stem from the
snapshot path, which only takes the first dot-segment. This broke names
containing dots (e.g. "Name.new" → "Name.new.luau" would produce
"Name.meta.json" instead of "Name.new.meta.json").
Strip the full middleware extension (e.g. ".server.luau", ".txt") from
the snapshot path filename instead. This correctly handles all cases:
Name.new.luau → Name.new → Name.new.meta.json
_Init.server.luau → _Init → _Init.meta.json
Name.new.txt → Name.new → Name.new.meta.json
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When a script/txt/csv child is renamed by name_for_inst (e.g. "Init" →
"_Init.luau"), the adjacent meta file must follow the same name. All
three callers were using the Roblox instance name to construct the meta
path, producing "Init.meta.json" instead of "_Init.meta.json" — which
collides with the parent directory's "init.meta.json" on
case-insensitive file systems.
Fix by deriving the meta stem from the first dot-segment of the
snapshot path file name, which already holds the resolved name.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When a child instance has a Roblox name that would produce a filesystem
name of "init" (case-insensitive), syncback now automatically prefixes
it with '_' (e.g. "Init" → "_Init.luau") instead of erroring. The
corresponding meta.json writes the original name via the `name` property
so Rojo can restore it on the next snapshot.
The sibling dedup check is updated to use actual on-disk names for
existing children and the resolved (init-prefixed) name for new ones,
so genuine collisions still error while false positives from the `name`
property are avoided.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replaces `serde_json` parsing with `jsonc-parser` throughout the
codebase, enabling support for **comments** and **trailing commas** in
all JSON files including `.project.json`, `.model.json`, and
`.meta.json` files.
MSRV bumps from `1.83.0` to `1.88.0` in order to
use the jsonc_parser dependency.