rojo/.cursor/rules/atlas-project.mdc
Joe e8dc9b09b9 Enhance documentation and update syncback features
- Updated the `audit.md` documentation to clarify the syncback process and the structure of the `FsSnapshot`.
- Revised the `atlas-api.mdc` to reflect changes in the Git metadata handling, including the introduction of a separate endpoint for fetching Git metadata.
- Improved the `atlas-dedup.mdc` to include handling for the reserved name "init" during slugification.
- Enhanced the `atlas-syncback.mdc` to document the new `SyncbackResult` structure and its integration with the syncback process.
- Updated various sections across multiple documentation files to ensure consistency and clarity regarding the project's architecture and API endpoints.

These changes aim to improve the overall understanding of the system and its components, facilitating better usage and integration.
2026-03-02 06:45:06 -06:00

400 lines
14 KiB
Text

---
alwaysApply: true
---
# Atlas Project File Format
> Atlas is a fork of Rojo. Many internal identifiers, API endpoints, and struct names still reference the original "Rojo" naming.
## Project File Schema
**Recognized files:** `*.project.json5` (preferred) | `*.project.json` (legacy)
**Special:** `default.project.json5` inherits parent folder name.
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `name` | string | Yes* | Instance name (*optional if `default.project.json5`) |
| `tree` | ProjectNode | Yes | Root instance tree structure |
| `$schema` | string | No | JSON schema URL for editor validation (preserved during syncback roundtrip) |
| `servePort` | number | No | Port for `atlas serve` (default: 34873) |
| `serveAddress` | string | No | Address to bind (default: `"127.0.0.1"`) |
| `servePlaceIds` | number[] | No | Only allow sync to these place IDs |
| `blockedPlaceIds` | number[] | No | Block sync to these place IDs |
| `placeId` | number | No | Set place ID on plugin connect |
| `gameId` | number | No | Set game/universe ID on plugin connect |
| `globIgnorePaths` | string[] | No | Glob patterns to ignore during sync |
| `syncRules` | SyncRule[] | No | Custom file type mappings |
| `syncbackRules` | SyncbackRules | No | Syncback configuration |
| `syncScriptsOnly` | bool | No | Only sync script instances (default: false) |
| `ignoreHiddenServices` | bool | No | Ignore internal services (default: true) |
| `fileLogLevel` | string | No | File logging level: "trace" (default), "debug", "info", "warn", "error", "none" |
```json5
{
"$schema": "https://raw.githubusercontent.com/UserGeneratedLLC/vscode-rojo/master/schemas/project.schema.json",
"name": "MyProject",
"tree": { /* ProjectNode */ },
"servePort": 34873,
"serveAddress": "0.0.0.0",
"servePlaceIds": [123456],
"blockedPlaceIds": [111111],
"placeId": 123456,
"gameId": 789012,
"globIgnorePaths": ["**/*.md", "**/node_modules/**"],
"syncRules": [/* SyncRule */],
"syncbackRules": { /* SyncbackRules */ },
"syncScriptsOnly": false,
"ignoreHiddenServices": true,
"fileLogLevel": "trace"
}
```
## ProjectNode Schema
Used in `tree` and recursively for all children.
| Field | Type | Description |
|-------|------|-------------|
| `$className` | string | Instance class (required for non-services) |
| `$path` | string | Filesystem path to sync from |
| `$id` | string | Unique ID for Ref property linking |
| `$properties` | object | Instance properties to set |
| `$attributes` | object | Instance attributes to set |
| `$ignoreUnknownInstances` | bool | Whether to ignore instances not in project during sync |
**Keys without `$` prefix are child instances.**
```json5
{
"$className": "Folder",
"$path": "src/MyFolder",
"$id": "unique-id",
"$properties": { "Anchored": true },
"$attributes": { "Health": 100 },
"$ignoreUnknownInstances": false,
// Children
"ChildFolder": { "$className": "Folder" },
"MyScript": { "$path": "src/MyScript.luau" }
}
```
**Services auto-inferred:** Workspace, ReplicatedStorage, ServerScriptService, ServerStorage, StarterGui, StarterPlayer, Lighting, Teams, Chat, SoundService, LocalizationService, TestService, etc.
## File Extension Mappings
### Scripts
| Extension | Result | RunContext | Note |
|-----------|--------|------------|------|
| `*.luau` | ModuleScript | — | Preferred |
| `*.server.luau` | Script | Server | Preferred |
| `*.client.luau` | Script | Client | Preferred |
| `*.plugin.luau` | Script | Plugin | |
| `*.local.luau` | LocalScript | — | |
| `*.legacy.luau` | Script | Legacy | |
| `*.lua` | ModuleScript | — | Legacy |
| `*.server.lua` | Script | Legacy | Legacy |
| `*.client.lua` | LocalScript | — | Legacy |
| `*.plugin.lua` | Script | Plugin | Legacy |
**Prefer `.luau`** — modern RunContext. `.lua` is legacy (still supported).
### Models & Data
| Extension | Result | Note |
|-----------|--------|------|
| `*.rbxm` | Binary model | |
| `*.rbxmx` | XML model | |
| `*.model.json5` | JSON model | Preferred |
| `*.model.json` | JSON model | Legacy |
| `*.txt` | StringValue | |
| `*.csv` | LocalizationTable | |
| `*.json5` | ModuleScript (Lua table) | Preferred |
| `*.json` | ModuleScript (Lua table) | Legacy |
| `*.toml` | ModuleScript (Lua table) | |
| `*.yaml`, `*.yml` | ModuleScript (Lua table) | |
### Meta & Project
| Extension | Purpose | Note |
|-----------|---------|------|
| `*.meta.json5` | Add properties/attributes to sibling | Preferred |
| `*.meta.json` | Add properties/attributes to sibling | Legacy |
| `*.project.json5` | Nested project | Preferred |
| `*.project.json` | Nested project | Legacy |
## Init File Priority
When directory has multiple init files, first match wins:
1. `default.project.json5` → Nested project (preferred)
2. `default.project.json` → Nested project (legacy)
3. `init.luau` → ModuleScript (preferred)
4. `init.server.luau` → Script (Server)
5. `init.client.luau` → Script (Client)
6. `init.plugin.luau` → Script (Plugin)
7. `init.local.luau` → LocalScript
8. `init.legacy.luau` → Script (Legacy)
9. `init.csv` → LocalizationTable
10. `init.lua` → ModuleScript (legacy)
11. `init.server.lua` → Script (Legacy)
12. `init.client.lua` → LocalScript (legacy)
**No init file?** → Directory becomes Folder. **Prefer `.luau` and `.json5` extensions.**
## Sync Rules Schema
Custom file type handling in `syncRules` array:
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `pattern` | string | Yes | Glob pattern to match files |
| `use` | string | Yes | Middleware type (see table below) |
| `suffix` | string | No | Extension to strip from instance name |
| `exclude` | string | No | Glob pattern to exclude from matching |
```json5
{
"syncRules": [{
"pattern": "*.foo",
"use": "moduleScript",
"suffix": ".foo",
"exclude": "*.test.foo"
}]
}
```
### `use` Values
| Value | Result |
|-------|--------|
| `serverScript` | Script (Server) |
| `clientScript` | Script (Client) |
| `moduleScript` | ModuleScript |
| `pluginScript` | Script (Plugin) |
| `localScript` | LocalScript |
| `legacyScript` | Script (Legacy) |
| `json`, `toml`, `yaml` | ModuleScript |
| `csv` | LocalizationTable |
| `text` | StringValue |
| `jsonModel`, `rbxm`, `rbxmx` | Instance tree |
| `project` | Nested project |
| `ignore` | Skip file |
## Syncback Rules Schema
Configure `syncbackRules` object for Roblox → filesystem sync:
| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `ignoreTrees` | string[] | `[]` | Roblox tree paths to skip (e.g., `"ServerStorage/Secrets"`) |
| `ignorePaths` | string[] | `[]` | Filesystem glob patterns to skip (e.g., `"src/generated/*"`) |
| `ignoreProperties` | object | `{}` | Properties to skip per class: `{"ClassName": ["Prop1", "Prop2"]}` |
| `ignoreClasses` | string[] | `[]` | Instance classes to skip entirely |
| `syncCurrentCamera` | bool | `false` | Whether to sync `Workspace.CurrentCamera` |
| `syncUnscriptable` | bool | `false` | Whether to sync unscriptable properties |
| `ignoreReferents` | bool | `false` | Whether to skip Ref properties (e.g., `Model.PrimaryPart`) |
| `createIgnoreDirPaths` | bool | `true` | Whether `/**` in ignore paths also matches the directory itself |
| `ignoreHiddenServices` | bool | — | Override root-level `ignoreHiddenServices` for syncback |
| `warnDuplicateNames` | bool | `false` | Warn on duplicate child names during syncback |
```json5
{
"syncbackRules": {
"ignoreTrees": ["ServerStorage/Secrets", "Workspace/Camera"],
"ignorePaths": ["src/generated/*", "src/temp/**"],
"ignoreProperties": {
"BasePart": ["Color", "BrickColor"],
"Script": ["Disabled"]
},
"ignoreClasses": ["Terrain", "Camera"],
"syncCurrentCamera": false,
"syncUnscriptable": false,
"ignoreReferents": false,
"createIgnoreDirPaths": false,
"warnDuplicateNames": false
}
}
```
## Meta Files
Add metadata to file-based instances. Meta files use **camelCase keys** (no `$` prefix -- that's only for ProjectNode).
**Adjacent meta** (e.g. `MyScript.server.meta.json5` for `MyScript.server.luau`):
```json5
{
"name": "Key:Script", // Override filename-derived instance name (slugify support)
"id": "unique-id", // For Ref property linking
"properties": { "Disabled": false },
"attributes": { "Priority": 1 },
"ignoreUnknownInstances": true
}
```
**Directory meta** (e.g. `init.meta.json5` inside a directory):
```json5
{
"name": "My:Folder", // Override directory-derived instance name
"className": "Configuration", // Override class (directory meta only)
"id": "unique-id",
"properties": { "Anchored": true },
"attributes": { "Health": 100 },
"ignoreUnknownInstances": false
}
```
**Key differences from ProjectNode:** Meta uses `className`, `properties`, `attributes` (camelCase, no `$` prefix). Adjacent meta does NOT support `className`.
**`name` field (slugify support):** When an instance name contains forbidden filesystem characters (`: / ? * < > | " \`), or is the reserved name `"init"` (case-insensitive, slugified to `"init_"`), syncback slugifies the filename (forbidden chars → `_`) and stores the real name in the `name` field. On forward sync, `name` overrides the filename-derived instance name. On collisions (e.g. `A/B` and `A_B` both slugify to `A_B`), `~2`, `~3` suffixes are appended and meta `name` fields distinguish them.
**`Rojo_Ref_*` attributes:** Meta files may also contain `Rojo_Ref_PropertyName` attributes written by syncback/two-way sync for Ref property linking. These are managed automatically and should not be hand-edited.
Meta files also support a `$schema` field (preserved during syncback roundtrip).
**Meta files CAN'T:** Set `$path`, have children.
## Model.json5 Format
Inline instance definition. Like meta files, model files use **camelCase keys** (no `$` prefix).
```json5
{
"name": "What?Model", // Override filename-derived name (slugify support)
"className": "Tool",
"id": "unique-id",
"properties": { "CanBeDropped": false },
"attributes": { "Damage": 50 },
"children": [
{
"name": "Handle",
"className": "Part",
"properties": { "Size": [1, 1, 3] }
}
]
}
```
**Note:** `children` is an **array** of child objects (each with a `name` field), not a map/object keyed by name. This differs from ProjectNode where children are flattened as keys.
## Property Formats
### Shorthand (Recommended)
```json5
{
"$properties": {
"Anchored": true, // Bool
"Health": 100, // Number
"Position": [0, 5, 0], // Vector3
"ImageRectSize": [100, 100], // Vector2
"Color": [1, 0, 0], // Color3 (normalized RGB)
"BrickColor": "Bright red", // BrickColor name
"Shape": "Ball", // Enum name
"Tags": ["Collectible", "PowerUp"], // Array
"Size": { "X": {"Scale": 1, "Offset": 0}, "Y": {"Scale": 0, "Offset": 100} }, // UDim2
"CFrame": { "position": [0, 5, 0], "orientation": [[1,0,0],[0,1,0],[0,0,1]] } // CFrame
}
}
```
### Explicit Type
Use when ambiguous or specifying enum by number:
```json5
{
"$properties": {
"Position": { "Vector3": [0, 5, 0] },
"Shape": { "Enum": 1 },
"BrickColor": { "BrickColor": 21 }
}
}
```
## Attributes
Same format as properties. Limitations: no Ref, no NumberSequence/ColorSequence, enums use string names only.
```json5
{
"$attributes": {
"Health": 100,
"Position": [0, 5, 0],
"MyFont": { "family": "rbxasset://fonts/families/SourceSansPro.json", "weight": "Regular", "style": "Normal" }
}
}
```
## Ref Property Linking
Two systems for linking instance references, both supported:
### Path-Based: `Rojo_Ref_*` (preferred, written by syncback/two-way sync)
Uses filesystem-name paths (slugified, dedup'd) to reference target instances:
```json5
// In meta file for an instance with PrimaryPart pointing to Handle
{
"attributes": {
"Rojo_Ref_PrimaryPart": "Workspace/MyModel/Handle.model.json5"
}
}
```
**Attribute format:** `Rojo_Ref_<PropertyName> = "<path>"`
Syncback writes **Luau-style relative paths**:
- `@self` / `@self/Child.luau` -- target is same instance or a descendant
- `./Sibling.luau` -- target is a same-parent sibling
- `../Uncle.luau` -- target is a parent's sibling
- `@game/Service/Path` -- cross-service reference
Forward sync resolves both relative and absolute formats via `resolve_ref_path_to_absolute()` + `get_instance_by_path()`. Path segments use full filesystem names (slug + extension + dedup suffix), matched case-insensitive with instance name fallback.
### ID-Based: `Rojo_Target_*` + `$id` (legacy, still read by forward sync)
Link instances via `$id` and special attributes:
```json5
{
"tree": {
"Target": { "$className": "Part", "$id": "myTarget" },
"Pointer": {
"$className": "ObjectValue",
"$attributes": { "Rojo_Target_Value": "myTarget" }
}
}
}
```
**Attribute format:** `Rojo_Target_<PropertyName>`
**Priority:** When both `Rojo_Ref_*` and `Rojo_Target_*` exist for the same property, `Rojo_Ref_*` takes precedence.
## Property Types
`String`, `Bool`, `Int32`, `Int64`, `Float32`, `Float64`, `Vector2`, `Vector3`, `Vector2int16`, `Vector3int16`, `UDim`, `UDim2`, `CFrame`, `Color3`, `Color3uint8`, `BrickColor`, `NumberRange`, `Rect`, `NumberSequence`, `ColorSequence`, `Enum`, `Ref`, `Content`, `Font`, `PhysicalProperties`, `Axes`, `Faces`, `Tags`, `Attributes`
See `rbx_reflection_database` for property listings per class.
## Validation Errors
1. Unknown fields (except children)
2. Reserved names starting with `$` as children
3. Missing `$className` or `$path`
4. `$path` to non-existent file
5. Invalid property types
6. Invalid glob syntax
7. Duplicate `$id`
## Source Files
- `src/project.rs` - Project parsing
- `src/snapshot_middleware/mod.rs` - Extension mappings
- `src/snapshot/` - Instance tree structure