Basic Mod Metadata specifications. #15
Replies: 2 comments 4 replies
|
Thanks for getting this started. Before the individual points, I noticed one thing across the list: I think the format should make that split explicit: who writes a field decides whether it can be automated at all, and that part is expensive to change once files are published. I want to make keeping the content manager up-to-date as easy as possible for both the content manager maintainers and also content creators. A lot of (4, 12, 13, 15) changes like an author tagging a release on GitHub or uploading to SpaceDock and goes to bed could be automated. At KSA's release pace, it could feel like a chore to update the content manager index each time a new release is pushed and/or easily be forgotten. So my suggestion: the author writes the first half (1, 2, 3, 7, 9, 10, 11, 14) once, and everything in the second half (4, 12, 13, 15) can be derived per release by tooling. Whether the two halves also live in two separate repositories like that is a different question, and I would leave it open for now. It only starts to matter the day something automated actually commits: GitHub protection rules are per branch, not per folder, so "humans need reviews on the authored files" and "the bot pushes unattended" do not mix well inside one repo, and one generated commit per mod release buries the history of the authored half over time. None of that hurts before the watcher exists. The one thing I would pin down early is the URL clients fetch the index from: if that is a stable address instead of a direct repo path, the storage layout stays our internal business, and we can start with one repo and still reorganize later without breaking anyone's installed client. It should IMO at least contain:
On 1 (ModId): agreed on the principle, and it is worth saying that this is not something we get to choose: I ran your regex against a few edge cases though, and it does not hold up:
And one thing no regex fix covers: folder names are case-insensitive on Windows and case-sensitive on Linux, so There is also a game-side landmine: So rather than patching the regex, I think the ModId deserves a small spec of its own that is deliberately stricter than the KSA implementation and independent from any filesystem, and everything expressive pushed into the display name (your 2).
On 4 (Version):
Agreed, and I would enforce it, not just recommend it.
I guess that is exactly why Borea has I would directly enforece it in the index isntead: a release whose version does not parse gets rejected at publish time, with the error in front of the mod author, instead of surfacing later as a weirdly sorted list in front of users. I would take SemVer 2.0.0 wholesale, including its pre-release ordering rules (they already give you the I would also build in a On 6 (Built For Game Version): this is the one where I disagree, and I opened #17 for exactly this question, so I will keep it short here and we can argue there. The core of it: KSA shipped roughly thirteen releases a month so far. With equality checks, every mod in the index is marked broken within days of each game update. And the "can be multiple" list has to grow by hand thirteen times a month to keep up. Your underlying instinct is right though, and #17 agrees with it: the version string as a whole really is not comparable. On 8 (Mod Dependencies):
An exact pin has the same cadence problem as 6: every release of a dependency invalidates every dependent. You can watch this happening in the existing CKAN index already where StarMap is pinned three different ways across the mods listed there (KSA-NetKAN#6). I would also allow at minimum min/max bounds instead of a single version. I would also widen the relationship kinds to at least this:
On 10 (Forums Post Link): Sounds good :) I would also have one optional set of more links (homepage, repo, forums, bugtracker, discord, ...). On 13 (Mod Size): we should derive 2 numbers: download size and install size on disk, since they might be different after compaction etc. |
|
Instead of more prose, here is the current proposal state as concrete files, using my own AdvancedFlightComputer mod as example. It combines the property list above, my earlier comment, RFC 0017 and RFC 0025, and the direction from #27 Please criticize fields, not abstractions: which field is wrong, missing, or should not exist. The authored file. Written once by the mod author, changed rarely when the mod's facts change: spec_version = 1
id = "AdvancedFlightComputer"
type = "mod"
name = "Advanced Flight Computer"
authors = ["Maxi"]
abstract = "Extra maneuver planning tools for Kitten Space Agency."
license = "MIT"
tags = ["control"]
# Where releases appear; the watcher picks new ones up from here.
[releases]
github = "Maximilian-Nesslauer/KSA-AdvancedFlightComputer"
[links]
forums = "https://forums.ahwoo.com/threads/advanced-flight-computer.783/"
repository = "https://github.com/Maximilian-Nesslauer/KSA-AdvancedFlightComputer"
spacedock = "https://spacedock.info/mod/4253/AdvancedFlightComputer"
bugtracker = "https://github.com/Maximilian-Nesslauer/KSA-AdvancedFlightComputer/issues"
# Oldest game version known to work, written the way the game displays it.
# Tooling resolves it to a revision when stamping a release (RFC 0017).
# A month is also accepted: game_min = "2026.7"
# game_max exists too and is optional; above it a client warns instead of blocking.
[compatibility]
game_min = "2026.8.3.5117"
# Only what a bot cannot derive: the loader needs authored version bounds,
# because the [StarMap] section of mod.toml deliberately carries none.
# min and max take SemVer values; max is optional, absent means open.
[[dependencies]]
id = "StarMap"
kind = "required"
min = "0.4.5"
max = "0.4.6"The generated file. Stamped by the watcher for every release, no human involved: {
"spec_version": 1,
"id": "AdvancedFlightComputer",
"type": "mod",
"version": "0.7.0",
"version_scheme": "semver",
"release_status": "stable",
"release_date": "2026-08-02T13:18:41Z",
"game_min": "2026.8.3.5117",
"game_min_revision": 5117,
"download": {
"url": "https://github.com/Maximilian-Nesslauer/KSA-AdvancedFlightComputer/releases/download/v0.7.0/AdvancedFlightComputer.zip",
"sha256": "ABC2A72E348AB26960FF59EDD019F160B12844099C30BF00F7D4E4D3D1ED5E74",
"size": 131042,
"content_type": "application/zip"
},
"install_size": 329449,
"install": [
{ "from": "AdvancedFlightComputer", "to": "mods", "derived": true }
],
"dependencies": [
{ "id": "StarMap", "kind": "required", "min": "0.4.5", "max": "0.4.6", "source": "authored" },
{ "id": "KittenExtensions", "kind": "optional", "source": "derived" }
],
"changelog": "https://github.com/Maximilian-Nesslauer/KSA-AdvancedFlightComputer/releases/tag/v0.7.0"
}Things worth noticing, because they answer questions from this thread:
And the decisions this example deliberately surfaces instead of hiding:
|
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Mod Managers and Indexers need to be able to store and use some metadata about mods. This post will talk about the bare minimum requirements for a mod's metadata to have a mod manager to function.
Properties
ModId: The unique constant Id of the mod. This should be the same name/id that is put in the
manifest.toml,mod.toml, and the mod folder's name. This should not be separated from the name/id put inmanifest.tomlas that will cause abstraction issues and Mod Dependency issues. These need to be unique to allow for any mod to have the capability to be loaded at the same time in KSA as well as to let Mod Managers and Indexers tell them apart. This needs to be constant across all mod versions to allow Mod Managers and Indexers to properly store them and resolve dependency issues. The ModId must also be cross-compatible with Linux, Windows, and MacOS to prevent any issues now and in the future, thus they must follow a regex to determine cross-compatibility and must be less than 256 characters. Example regex I looked up,^(?![\/:*?"<>|])[\w\s.-]+(?![\s.])$.Display Name: The name displayed by Mod Managers which can be of indeterminate length and contain characters that ModId would not permit.
Authors: The authors of the mod.
Version: The version of the mod. My thought is to use a standard
Major.Minor.Patch[-PreRelease]style for versioning as it is common and easy to understand if a version is newer or older. As for the PreRelease, it will use standard-alphais older than-betafor matching versions, with-zetabeing the newest before full release (Although I doubt a mod will use anything past-beta).Description: The description of the mod.
Built For Game Version: Which KSA Version this mod was built for, can be multiple. Due to KSA's versioning system being quite unique and not fully reliable, my thought is to only have equality checks (does this version equal the other exactly) rather than a range. Hence why there can be multiple versions KSA is built for.
Mod Loader: If the mod is intended for use with a mod loader, which mod loaders, and if it can be used without one.
Mod Dependencies: A list of
(ModId, Version)that this mod requires to be installed to work.Source Code Link: A link to the source code of the mod.
Forums Post Link: A link to the KSA Forums about this mod release. This is to obey the KSA modding rules and to help with bot accounts as the mod poster will need an Ahwoo account.
License: The license of the mod. Can be either the name of a license (for popular ones) or a path to the license file.
Release Date: The release date (and time?) of this version of the mod.
Mod Size: The size in bytes of all the mod files, not including the metadata. This will be used to show the user how big the mod is.
Tags: A list of tags/categories the mod falls under (Parts, Code, Sounds, Tools, etc.).
Changelog: The changelog of this specific version. could be a string or maybe a link/path to view the changelog?
These are not all of the metadata properties for mods, they are just the most important ones I could think of off the top of my head. If you see any issues with any of them please comment.
All reactions