Skip to main content

Project Structure & Storage

Rhumb adopts a unique nomenclature for its file artifacts to distinguish between executable scripts and library code.

Artifact Terminology

TermConceptStandard ExtOptional Ext
LetterScript / Executable. A one-off action. Runs standalone..rh.rhl
BookModule. A single file containing library code. Accesses its Shelf directly..rh.rhb
ShelfFolder. A directory containing Books and/or inner ShelvesN/AN/A
RouteApplication. A collection of Shelves/Books meant to be run by an end user..riN/A
LibraryPackage. A collection of Shelves/Books meant to be used by other Libraries or Routes..riN/A
CatalogMetadata. Defines Library properties.@.rhy@.rh.yaml

Shelf Organization

In Rhumb, a file's "package" is defined solely by its parent directory.

  • No Headers: There are no package or namespace declarations inside .rh files.
  • Implicit Scope: A Book can access any other Book within the same Shelf (Folder) implicitly.
  • Identity: While the folder structure defines grouping, the Catalog (.rhy) defines identity. The folder tells the compiler "these files are one unit," but the Catalog tells the compiler "this group of files is the math shelf."

Libraries & Catalogs

External dependencies are defined via Catalogs.

  • Format: YAML files with the extension .rhy or .rh.yaml with the @ character in the filename.
  • Naming Convention: LibraryName@SubCatalog.rhy
    • Example: networking@http.rhy
    • Anonymous Project: ___@config.rhy (Project name defined inside the YAML).
  • Role: The Catalog is the Authority on:
    • Versioning: Mapping a physical folder (e.g., src/0.1.0) to a semantic version.
    • Integrity: Storing the Anchors (Checksums) for dependencies.
    • Aliasing: Naming dependencies (e.g., mapping math to 🧮).

Language Localization

For Books managed by the IDE or build tool, the source code is decomposed into three file types to support Localization and Git workflows:

  1. Logic Node (.__.rh): The Canonical AST
    • Format: filename.__.rh
    • Content: Rhumb source using Raw IDs ($x9A2, $L01) instead of human labels
    • Role: This is the Source of Truth for the compiler. It ensures referential integrity across renames and languages.
  2. Translation Map (.rhy): The Label Dictionary (YAML syntax)
    • Format: filename.rhy
    • Content: A YAML map of IDs to localized strings
    $x9A:
    en_US: velocity
    fr_FR: vitesse
    $d1B:
    en_US: distance
    fr_FR: distance
  3. Localized Artifacts (.<lang>.rh): Read-Only Views
    • Format: filename.en_US.rh
    • Content: Valid Rhumb source generated by the IDE using the Logic Node + Translation Map.
    • Role: Allows browsing the code in specific languages (e.g., on GitHub/Gitlab) without needing the Rhumb IDE.

Dependency Resolution

Dependencies are imported using the Resolver Protocol.

  • Explicit Version: { ! | math | 1.0.0 }
  • Latest/Default Version: { ! | math | - } (Use - to indicate no specific version)
ResolverSyntaxUse CaseExample
Base!Standard Libs{!|🧮|-}
Local-Internal Code{-|src\utils\math |-}
Resource=Static Assets{=|assets/icons/logo.png |-}
CustomgitExternal Libs{git|https://github...|0.1.0}
Native_Internal FFI{_|nat_math|-}

Path Resolution Rules:

  1. Implicit (Sibling): Books within the same Shelf (Folder) can access each other directly by label. No import block is required.
  2. Local Resolver (-): The Local Resolver {-} performs a Two-Step Lookup:
    • Step A (Logical Alias): It first checks the active catalog@.rhy for a dependency key matching the provided label (e.g., math). If found, it resolves to the version or path defined in the catalog.
    • Step B (Physical Path): If no alias is found, it treats the string as a File System Path relative to the Project Root (e.g., src/libs/math).

Version Syntax & Resolution: The Resolver interprets the Type and Format of the literal provided in the version slot. Rhumb uses the .- (DotDash) syntax to explicitly signify wildcards.

Note on Suffixes: Version literals may include prerelease (-alpha) and build (+001) suffixes. These are treated as Strict Text Matches by the resolver; wildcards cannot be used in conjunction with suffixes.

LiteralSyntaxTypeSemanticsTarget Match Example
1.2.3X.Y.ZVersionExact Pin. Must match exactly./lib@1.2.3
1.2.3-rcX.Y.Z-PreVersionExact Pin with Pre-release./lib@1.2.3-rc
1.2.-X.Y.-VersionPatch Wildcard. Highest patch for 1.2./lib@1.2.9
1.-X.-FloatMinor Wildcard. Highest minor/patch for 1./lib@1.9.4
-DashDashMajor Wildcard / Working Copy. Prefers unversioned Shelves./lib
1XIntegerImplicit Major. Same as 1.- (SemVer ^1.0)./lib@1.9.4
stableLabelLabelVariable. Looks for a matching variable that contains a Version.

Circular Dependencies: Rhumb supports circular references between Shelves for declarations because of the multi-pass Hoister. However, circular initialization logic (top-level code that depends on another file's top-level code executing first) will trigger a Runtime Cycle Error.

Custom Network Resolvers (git & !)

Under the hood, both the Remote (git) and Base (!) resolvers are Custom Resolvers that use network protocols (Git over HTTP) to transmit libraries. They differ only in how they determine the Target Repository and the Target Branch.

  1. Git Resolver (git):

    • Mechanism: Connects to the Provided URL (e.g., a GitHub/GitLab repo).
    • Target: Pulls the HEAD Branch of that repository.
    • Usage: { git | https://github.com/user/repo | version }
  2. Base Library Resolver (!):

    • Mechanism: Connects to a Default URL (The official Rhumb Library Registry).
    • Target: Pulls the Provided Branch/Tag that matches the requested library (e.g., library "🧮").
    • Default URL: https://github.com/rhumb/libraries
    • Override: The source URL can be changed via project metadata (see below).

Initial Library State

A resolved module is not just a bag of code; it must be explicitly granted capabilities to interact with the outside world through a Vassal.

% { resolver | path | version }
dlib := {- | dangerous_library | -}

When this statement executes, the runtime performs a two-stage security handshake:

  1. Integrity Check (The Anchor): The Loader calculates the SHA-256 hash of the downloaded artifact and compares it against the entry in the catalog.rhy. If they mismatch, the VM halts with a SupplyChainViolation.
  2. Capability Grant (The Vassal): By default, imported modules have Zero Ambient Authority. They can perform pure logic (math, data transformation) but cannot access the Network, Disk, or Environment unless explicitly piped into a Vassal that grants those permissions.

To grant permissions, provide the raw library as an argument to a Vassal (to define the vassal directly after the library import, you can use the Pipe Operator (||)).

vassal .= <{
#🚀(%( permissions... %))
}>
dlib := vassal({-|dangerous_library|-})

% or using the pipe operator
dlib := {-|dangerous_library|-} || <{
#🚀(%( permissions... %))
}>

Signal Pattern Ranges

Capabilities are expressed as Signal Patterns on the system channels.

System Channels:

GlyphChannelPurpose
#📡NetworkHTTP, Sockets, Fetch
#💾DiskFile System Read/Write
#🚀ExecSubprocesses & Shell
#⚙️EnvEnvironment Variables

The IO Range Syntax (|): Capabilities are defined as Ranges representing the boundary between the module and the system.

  • Format: Ingress | Egress
  • Ingress (Left): What the module reads/accepts (File Reads, Port Listens).
  • Egress (Right): What the module writes/sends (File Writes, Outbound Connections).
  • Deny (___): Use the Empty value to block a side of the boundary.

Example: A Secure Import

% Import a weather library.
% We grant it Network access (to specific domains) but deny Disk and Env access.

weather := {git|https://github.com/weather/api|1.0.0} || <{
% 📡 Network
% Ingress: Listen on port 8080 (Callback)
% Egress: Connect to api.weather.com
#📡( 8080 | "api.weather.com" )

% ⚙️ Environment
% Ingress: Read the API key
% Egress: Blocked (Cannot change Env)
#⚙️( "WEATHER_API_KEY" | ___ )

% Implicitly Deny: #💾 (Disk) and #🚀 (Exec)
}>

If the weather library attempts to read /etc/passwd (emitting #💾("/etc/passwd" | ___)), the Vassal will fail to match the pattern, and the signal will dissolve into ___ (Empty), effectively sandboxing the code.

Catalogs

Catalog files serve a dual purpose: they are both the Dependency Manifest (Human Intent) and the Integrity Anchor (Machine Reality). Rhumb differentiates between Code Dependencies (YAML Strings) and Resource Dependencies (YAML Strings inside Arrays). A catalog file must have the same name as the folder but with @ followed by any additional label (for breaking a catalog into multiple files).

The Anchor Protocol

Every dependency entry in the catalog must eventually include an anchor (cryptographic checksum). This "freezes" the dependency to a specific sequence of bytes, preventing "Left-Pad" incidents or malicious updates.

Catalog Format w/ Anchors:

project@.rhy
-:
# === Code Dependencies ===
# Format: "alias: [version] [anchor]"

# 1. Secured Dependency (Production Ready)
# The loader verifies this SHA-256 before compiling.
physics: 1.2.0 sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855

# 2. Unsecured Dependency (Development)
# The "___" indicates the anchor is missing.
# The wildcard in the version indicates that this is a new not-yet pinned dependency.
# the contract hear should be a match or a more restrictive contract than the one in the book's library resolver.
# The IDE will calculate the actual version and the anchor this on the next successful run and update the file.
graphics: 1.0.- ___

# 3. Base Library (Verified)
# Resolvers '!' treat the base library like any other dependency.
# They must be anchored to ensure the runtime environment hasn't been tampered with.
std_math: 🧮@1.0.0! sha256:8f4b2...

# 4. Local Resolver (Implicit Trust)
# Only the Local Resolver '-' is exempt from anchoring, as it represents the
# mutable source code of the project itself.
local_utils: utils/-

# === Resource Dependencies ===
# Format: "filename: [anchor]"
assets:
- -: # the initial dash indicates this is a bracketed sub-catalog
logo.png: sha256:a1b2...
data.json: ___
  1. Mandatory Tip (-): Every catalog must contain a Tip version key (-). This represents the "Working Copy" or "Dev" state of the project. It cannot be null; it must contain either a dependency map or a pointer.
  2. Immutability: Numbered versions (e.g., 0.1.0) are immutable. Once published/tagged, their dependency list should not change. The Tip (-) is mutable.

Integrity Enforcement & The -sha256 Flag

Rhumb enforces strict supply chain security at runtime. When rhi starts (either in file mode or REPL mode), it scans the local directory for a catalog and recursively validates that all dependencies and resources match their defined anchors.

The CLI Flag: -sha256 This flag controls the Auto-Anchor behavior. It does not change the execution mode (File vs. REPL); it only determines whether the runtime is allowed to update the catalog file.

CommandBehavior
rhi -sha256 file.rh1. Scans catalog at file's location.
2. Replaces any ___ anchors with calculated checksums.
3. Validates existing anchors (Panics on mismatch).
4. Executes file.rh.
rhi file.rh1. Scans catalog at file's location.
2. Panics if any ___ anchors are found.
3. Validates existing anchors (Panics on mismatch).
4. Executes file.rh.
rhi -sha2561. Scans catalog at current location.
2. Replaces ___ with checksums.
3. Validates existing anchors.
4. Starts REPL.
rhi1. Scans catalog at current location.
2. Panics if ___ found.
3. Validates anchors.
4. Starts REPL.

Panic Conditions: The runtime will halt immediately with a specific error message if integrity checks fail:

  • Empty Anchor (without -sha256):

    anchor is not a match for dependency 'libs/math' (line 12, col 4): expected '___' actual 'sha256:e3b0c4...'

  • Mismatching Anchor (always):

    anchor is not a match for dependency 'libs/math' (line 12, col 4): expected 'sha256:8f4a...' actual 'sha256:e3b0c4...'

Catalog Metadata (User-Defined in .rhy)

A catalog file can contain one non-version key which is the project's name (best practice is that this matches the folder's name). This non-version key hold's an object with a few metadata fields:

Emoji KeyNameTypeDescription
👤AuthorStringThe maintainer or organization.
🪪LicenseStringSPDX license identifier.
📦RepoURLSource code repository.
🏷️TagsListKeywords for indexing/search.
📝DescStringMulti-line description.
📂RootPathSource Root. If set (e.g. src), all shelf lookups happen relative to this folder.
Base URLURLBase Library Override. Changes the default registry for ! imports from github.com/rhumb-lang/libraries to a custom Git URL.
⚙️EnginesMapRuntime Requirements. Specifies the minimum version of the runtimes (such as rhi) required to use this library. Used to ensure Native Functions exist.

Engines Example:

my_project:
⚙️:
rhi: "0.1.0" # Indicates that my_project works with the `rhi` runtime at version 0.1.0

Example Library/Route Folder

Since Rhumb is managed by an IDE, the Working Copy is decoupled from the Archived Versions.

Instead of editing files directly inside of the numbered version folder (which changes name), you perform all work in the "top shelf" (-) (which never changes name). When you "bump" a version, the IDE snapshots that folder into a numbered archive. These folders sit alongside the shelves or other resource folders of the project.

$ tree . # inside of a Rhumb project
/project_name
├── project_name@.rhy
└── /src
├── /- <-- Root Project Tip
│ └── +main.rh
├── /0.1.0 <-- Root Project Version
│ └── +main.rh
├── /core_mechanics
│ ├── /-
│ │ ├── player.rh
│ │ └── movement.rh
│ ├── /0.3.2
│ │ ├── player.rh
│ │ └── movement.rh
│ └── core_mechanics@.rhy
├── /physics
│ ├── /-
│ │ ├── particle.rh
│ │ └── ball.rh
│ └── /0.1.0
│ ├── particle.rh
│ └── ball.rh
├── /art_files
│ ├── /-
│ │ ├── hero.png
│ │ ├── map.json
│ │ └── enemy.png
│ ├── /0.2.0
│ │ ├── hero.png
│ │ └── map.json
│ └── /0.1.0
│ ├── hero.png
│ └── map.json
└── /integration_checks
├── /-
│ └── +integration_checks.rh
├── /0.5.0
│ └── +integration_checks.rh
├── /0.4.0
│ └── +integration_checks.rh
├── /0.3.0
│ └── +integration_checks.rh
├── /0.2.0
│ └── +integration_checks.rh
└── /0.1.0
└── +integration_checks.rh

Runtime Metadata (Resolver-Generated)

This is what the LibraryLoader generates and stores in memory (or the .ri snapshot) after scanning the disk.

FieldTypeSourcePurpose
ResolvedVersionStringCalculatedThe concrete SemVer (e.g., 1.2.3).
PhysicalPathPathCalculatedAbsolute path to the shelf directory (e.g., /abs/project/src/physics/0.1.0).
EntryPointPathScannedThe absolute path to the +filename.rh file found in that directory. null if it's a library-only shelf.
DependenciesListCatalogPre-calculated list of dependencies for this specific version.
IntegrityHashCalculatedSHA-256 of the shelf contents (for security/caching).

Dependency Aliasing

The keys in the Dependencies block act as Logical Aliases. This allows you to rename libraries or move them without changing your source code imports.

Catalog Example:

project@.rhy
-:
# logical_name : [ original_name @ ] specific_version_or_path
physics_engine: libs/physics ___
game_math: math@0.1.0 ___ # to make an alias, prefix the version name and an "@" before the version
standard_math: 🧮@1.0.0! ___ # IDE will calculate sha256 of the local stdlib on disk

Source Example:

% main.rh
% Import using the alias, not the path
phys := {-|physics_engine|-}
math := [
base .. {-|standard_math|-}
game .. {-|game_math|-}
]
n := math\game\random()

The Pointer Protocol (<-)

To reduce duplication, a version can inherit dependencies from another version using the Pointer Key (<-).

Syntax:

-:
<-: 0.1.0 # Base: Inherit everything from 0.1.0
dev_tools: 2.0.0 # Extension: Add a new tool for development

Rules of Inheritance:

  1. Extension (Allowed): You can include the pointer <- alongside New Keys. The runtime merges the pointed version's dependencies with the new keys.
  2. Shadowing (Forbidden): You cannot override a dependency that already exists in the pointed version. If you need to change a version of an inherited library, the pointer is considered Invalid.
    • Mechanism: The IDE or build tool will "Hoist" (flatten) the dependencies: it removes the <- pointer and copies all keys from the target version up to the current version, effectively decoupling them. This ensures explicit visibility of all dependencies when they diverge.

Resource Shelves & Slips

Static assets (images, JSON configuration, database files) are imported using the Resource Resolver {=}. Unlike code imports which load a "Shelf," resource imports load a specific File.

Syntax: { = | path/to/shelf/filename.ext | version }

The Bracketed Protocol

Resource Shelves are denoted by surrounding the version or sub-catalog in a YAML Array ([]).

  1. Catalog Definition: name: [version]
  2. Disk Location: The loader automatically looks for a folder named [name].
  3. Versioning: _ Versioned: [1.0.0]src/[name]/1.0.0/ _ Tip: [-]src/[name]/-/ _ Inline: [{...}]src/[name]/-/ (The version is implicitly Tip-based). _ Block:
    -:
    art_files: # yaml has a dash block syntax that means []
    - -:
    image.png: sha256:d4c3...
    0.1.0:
    image.png: sha256:fa3f...
    # equivalent inline
    <!-- prettier-ignore -->
    art_files2: [{-: {image.png: sha256:d4c3...}, 0.1.0: {image.png: sha256:fa3f...}}]

Example:

art_files@.rhy
-:
<-: 0.1.0 # uses dependency graph for 0.1.0
# if any files change from 0.1.0, the pointer can no longer be used
# if only new files are added, the pointer can still be used alongside the new key-value resource pairs
0.1.0:
# --- Auto-Discovery ---
# Inferred from extension (.json -> Map, .png -> Binary)
config.json: sha256:a1b2c3...
hero.png: ___ # system will add checksum on next run

# --- Explicit Options (Key Suffix) ---
# Force specific encoding or MIME type via semicolon
legacy.data;iso-8859-1: sha256:e3b0c44...
raw_config.json;text/plain: sha256:c1c149af... # Load as Text, do not parse

# --- Integrity & Security ---
# Checksums are required, the loader validates the bytes before returning.
secure.db: sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855

Constraint: Resource filenames defined in the catalog must not contain semi-colons (;). If a file on disk has one, it must be renamed to be compatible with the Symbolic Protocol.

Generation: Setting the value to ___ acts as a request for the IDE or Build Tool to calculate the SHA-256 hash and update the catalog file. The Runtime (VM) will throw an error if it encounters ___ in a production/frozen environment, enforcing integrity.

Runtime Behavior Matrix

The Loader determines the return type based on the MIME type, which is either inferred from the file extension or explicitly overridden in the catalog.

File ExtensionDefault MIMERuntime ValueDescription
.jsonapplication/jsonMapAutomatically parsed into a Rhumb Map.
.txt, .rtf, .mdtext/plainTextLoaded as a UTF-8 string.
.png, .jpg, etc.image/*SlipReturns a lightweight slip (see below).
.db, .sqliteapplication/x-sqlite3SlipReturns a slip for DB drivers.
(Unknown)application/octet-streamSlipRaw binary slip.

Options & Overrides

You can modify the loading behavior by setting various options in the catalog entry for a resource.

  • utf-8 / iso-8859-1: Forces text decoding using the specified charset.
  • base64: Loads binary data but returns it as a Base64-encoded Text string.
  • text/plain: Forces treating a file (like .json) as raw text instead of parsing it.
  • application/json: Forces parsing a file (like .config) as JSON.

Options can be defined in two places:

  1. In the Key (Suffix): filename;option: anchor
    • Best for: Loading Instructions (e.g., base64). This allows the IDE to auto-generate the anchor (___ -> sha256:...) without overwriting your manual options.
  2. In the Value (Prefix): filename: option anchor
    • Best for: File Metadata (e.g., text/plain). Cleaner to read but requires care when auto-generating anchors to preserve the existing text.

Example:

[logo_folder]@.rhy
-:
# Key-based (Safe for Auto-Anchor)
logo.png;base64: ___

# Value-based (Clean Readability)
config.json: text/plain sha256:e3b0c442...

# Mixed (Valid)
data.dat;base64: application/octet-stream sha256:a1b2...
  • Tooling (rhide): Your future IDE or build tool logic for replacing ___ with sha256:... becomes slightly more complex.
    • Old Logic: Value = newHash
    • New Logic: Value = oldOptions + " " + newHash (Must preserve existing prefix tokens).
  • Conflict Resolution: If a user specifies text/plain in the key AND application/json in the value, the loop in parseResourceMeta will let the last one win (based on iteration order).

Slips (Resource Handles)

For binary assets (images, audio) or large files (databases), loading the entire content into the VM stack is inefficient. In these cases, the Resolver returns a Slip which is a resource handle.

  • Type: Slip

  • Fields:

    • \path: The absolute path to the verified file on disk.
    • \mime: The resolved MIME type.
  • Usage: Base library functions accept slips directly.

    db_res := {=|database/users.db|0.1.0} % Returns Slip
    conn := sql\open(db_res) % Opens the path defined in the slip

Semantics: A Slip represents Verified Permission to access a specific asset. It does not load the asset into memory.

Streaming: Base library functions (like io\open(slip)) use the Slip to open a file descriptor, allowing for random access and streaming of large assets (video/databases) without memory pressure.

Security: Slips are Opaque Handles. They cannot be constructed manually via Map literals. This ensures that all Slips passed to base library functions have originated from the verified Resolver logic and point to sandboxed, checksummed assets.

The Entry Point (+)

The entry point of any Shelf (local library) is strictly defined by the file naming convention.

  • Syntax: +filename.rh
  • Constraint: A Shelf version may contain only one file with the + prefix.
  • Behavior:
    • Run: When rhi ./shelf is called, the interpreter locates the + file and begins execution there.
    • Import: When a module is imported by another, the + file is treated just like any other source file in the bundle (its code is loaded), but it acts as the "Leader" of the loading order.
  • Library Mode: A Shelf with no + file is a Library. It cannot be executed directly.

Example:

/my_game
├── +foo.rh <-- The "Main" script.
├── logic.rh
└── _helpers.rh <-- A standard source file.

Shelf Scope (Internal Visibility)

Rhumb uses a "Flattened Directory Scope."

  • The Rule: All files within a single Shelf version (e.g., inside /0.1.0/) share the same scope.
  • Mechanism: You do not need to import sibling files. If logic.rh defines CalculateScore, +foo.rh can call it instantly.
  • Privacy Exception: This shared scope includes Private (_) members. Privacy is only enforced across Shelf boundaries, not within the Shelf itself.

External Visibility (Exports)

Visibility is controlled entirely by the Label Naming Convention.

Public by Default

Any top-level label (function, variable, constant, key) that does not start with an underscore is automatically exported.

  • Definition: calculate := [] -> ( ... )
  • Access: Visible to any library or route that imports this Shelf.

Private by Prefix (_)

Any top-level label starting with an underscore _ is strictly internal.

  • Definition: _validate .= [] -> ( ... )
  • Access:
    • Visible to sibling files (e.g., logic.rh can call _validate defined in helpers.rh).
    • Invisible to importers (e.g., if Game imports Physics, it cannot see Physics\_validate).

Visual Example

File: /physics/collision.rh

% Public: The world can see this
check-overlap .= [a;, b] (
_boxes_touch(a; b) => (
...
)
)

% Private: Only the 'physics' shelf can see this
_boxes_touch .= [a; b] -. (
...
)

File: /game/+main.rh

phys := {-|physics|1.-}

% Valid
phys\CheckOverlap(p1; p2)

% Error: '_boxes_touch' is not defined in library 'physics'
phys\_boxes_touch(p1, p2)

Full Catalog Example

./my_project@.rhy
# one non-version key is allowed for project/shelf metadata
my_project:
👤: Jake Russo # author
🪪: MIT # license
📦: https://github.com/user/repo
🏷️: # keywords
- programming
- cryptography
- server
📝: >
This is a description of the project and it can span
multiple lines using thr yaml ">" operator
📂: src # if the libraries and desktop books are in non-root folder
: "https://git.internal.corp/rhumb/custom-std-lib" # Override the base library source

# all remaining values in the catalog are versions of the project
-:
<-: 0.1.0 # Inherit base dependencies from 0.1.0
debug_tools: 1.0.0 # EXTENSION: Allowed. Adds 'debug_tools' to the set.
# physics: 1.0.0 # SHADOWING: Forbidden. If you uncomment this, the IDE will
# remove the '<-' pointer and copy all 0.1.0 deps here.
0.1.0:
core_mechanics: <- # this "<-" symbol as a value means that core_mechanics shelf contains its own catalog
win_conditions: <-
physics: # objects with version keys means that the shelf's catalog is included here
0.1.0:
# the triple underscore ____ means that the user has not yet added an achor for these shelves
core_mechanics: 0.3.2 ___ # this means that physics@0.1.0 depends on core_mechanics@0.3.2
math: 0.1.0! ___ # the ! means base library (all standard libraries are versioned and anchored)

# The brackets indicate this is a Resource Shelf.
art_files: [0.1.0] ___ # Maps to: /src/[art_files]/0.1.0

# if you are using the flag for allowing wildcards, you could reference the tip version directly
sounds: [-] # Maps to: /src/[sounds]/-
# if you want to specify a resource sub-catalog across multiple lines, use dash - leading line to indicate []
icons: # Maps to: /src/[icons]
- -: # the leading dash tells yaml that this is an array (which is how we identify resource shelves)
logo.png: sha256:a1b2...
favicon.ico: sha256:c12f8... # multiple preceding YAML dashes are not required
spinner.gif: ___

# false means that this is a non-resource folder that should be excluded from any distribution
integration_checks: false # but it could still have its own catalog (like for testing routes)
---
# ./core_mechanics/core_mechanics@.rhy
-: null # since none of the versions contain dependencies, no pointer is needed
0.4.1: ~ # in YAML ~ is equivalent to null
0.3.2: null # null means that this is a rhumb folder but there's no dependencies and no inner shelves
---
# ./win_conditions/win_conditions@.rhy
-: # we're using the new core_mechanics version in this top shelf
core_mechanics: 0.4.1
physics: 0.1.0
0.2.1:
core_mechanics: 0.3.2
physics: 0.1.0
0.2.0:
core_mechanics: 0.3.2
physics: 0.1.0
---
# ./integration_checks/integration_checks@.rhy
# even though this shelf isn't part of the main library/route, it can still have a catalog
-:
<-: 0.5.0
0.5.0:
<-: 0.4.0 # if you are adding only, you can keep the pointer
win_conditions: 0.2.1
0.4.0:
core_mechanics: 0.4.1
physics: 0.1.0
0.3.0:
core_mechanics: 0.3.2
physics: 0.1.0
0.2.0:
<-: 0.1.0
0.1.0:
physics: 0.1.0