HumankindAssetFramework

Design note — headless CLI (make HAF operable by AI/automation)

BUILT — see Headless-CLI.md for the real, current reference. rebuild-model + clean verified; build-mod wired to the game’s own ModuleEditor.BuildModification (full build+deploy, headless). This file is the original design/reasoning; the “build-mod needs discovery / build stays in the editor” speculation below was superseded once the Mercury ▸ Mod Editor build method was found and called via reflection.

Status: designed, not built. The documentation work made HAF readable by AI (llms.txt, the Pages site). This is the complement: a command-line surface that makes the editor’s functions operable without the GUI — so an agent, a script, or CI can author, validate, and bake content the same way a human does in Tools ▸ HAF, minus the clicking.

Premise

Unity + the ENCReload project are already a hard requirement to use the authoring tools. A batch-mode CLI therefore adds no new requirement — it just drives the existing, GUI-free pipeline from the command line. The bake tests already prove this works: BakeSmokeTest / BakeFeatureTest run the real ConfigFor → UniversalBaker path as static methods with no window open. The CLI is the same invocation, parameterised.

What can run where (the boundary)

Capability Needs Unity? How
Edit data-only registries (resize, formations, era, sound overrides, retexture config) No plain JSON (pack.json, haf_*.json) — editable directly or by a standalone verb
Validate a pack (bones/paths/GUIDs/schema) No (mostly) the pack validator core — pure logic + file checks
Convert a model file (GLB/glTF/OBJ/FBX) No glbconv.exe (already standalone)
Blender prep (rig/decimate/clip extract) No already headless (blender -b)
Bake Skeleton / Atlas / ClipCollection / district FxMesh Yes the Amplitude SDK is Unity-bound → Unity batch mode

So: everything except baking the Amplitude assets can run with no Unity at all; baking runs headless in Unity batch mode. There is no way to bake Amplitude assets on a machine without Unity — that’s the one hard limit, stated plainly.

“Can’t we reverse-engineer the editor to drop Unity?”

Two different targets hide behind this:

Execution model

A single entry class HAF.Cli in the ENCReload editor assembly (where ConfigFor/UniversalBaker/the registries live), invoked via:

Unity.exe -batchmode -quit -projectPath <ENCReload> -logFile - -executeMethod HAF.Cli.Run -- <request.json>

wrapped in a small haf shim (.bat / .sh) so callers don’t hand-write the Unity path. -batchmode -quit means no GUI and a clean exit; -logFile - streams to stdout.

Fast path (optional): pure-data verbs (validate, list, simple registry edits) touch only JSON and need no Unity — they can be a standalone .exe (like glbconv) to avoid Unity’s ~1-minute batch startup per call. Recommended split: standalone for data/validate (instant), Unity batch mode for bake (necessarily slow). One requirement, two speeds.

Command surface (proposed)

Request in, structured result out — no interactive prompts (batch mode has no console input).

Verb Unity? Does Reuses
list [--kind models\|districts\|formations\|sounds] no dump current registry entries as JSON the registries
validate <pack> no pre-flight content check → {warnings, errors} ValidateEntry (validator)
bake <request.json> yes bake one model/district/prop from a JSON bake request → produce assets + upsert registry ConfigForUniversalBaker
set-resize / set-formation / silence-sound no scripted data-only edits (thin wrappers over the registries) ModelRegistry etc.

bake request = the JSON form of a BakeConfig (model file, pawn, size, shading, animated/clip, strip, etc.) — the same fields the Factory/Animation Lab collect. Mapping through ConfigFor (the single shared config path the GUI and the tests already use) means the CLI can’t drift from the GUI’s behaviour.

Machine-readable contract (the point of it, for AI)

The two verbs the real workflow needs

A rebuilt model isn’t in the game until the mod is built (“referencing ≠ rendering — it needs a Build for the MeshCollection”). So the CLI needs both, and they differ sharply in difficulty:

Phasing

Non-goals / risks