# Prometeu Packer (prometeu-packer) — Specification (Draft)

> **Status:** Draft / Community-facing
>
> This document specifies the **Prometeu Packer**, the tooling responsible for **asset management** and producing two build artifacts:
>
> * `build/assets.pa` — the ROM payload containing packed asset bytes
> * `build/asset_table.json` — a machine-readable descriptor of the packed assets
>
> The Packer is deliberately **agnostic of cartridge shipping**. A separate **Cartridge Shipper** (outside the Packer) consumes `build/asset_table.json` to generate the final `cartridge/manifest.json`, copy `assets.pa` to the cartridge directory, and zip the cartridge into a distributable format.

---

## 1. Goals and Non-Goals

### 1.1 Goals

1. **Be the guardian of sanity** in a constantly mutating `assets/` workspace.

    * Users may be disorganized.
    * The directory may contain WIP, junk, unused files, duplicates, outdated exports.
    * The Packer must help users identify and fix mistakes.

2. Provide a robust, deterministic, **tooling-grade** asset pipeline.

    * Stable asset identity.
    * Deterministic packing order.
    * Reproducible output bytes.

3. Support both **raw (direct) assets** and **virtual assets**.

    * Raw assets: the payload in ROM is exactly the source bytes.
    * Virtual assets: the payload is derived from multiple inputs via a build pipeline (e.g., PNG + palettes → `TILES` payload).

4. Produce an output descriptor (`build/asset_table.json`) suitable for:

    * a Cartridge Shipper to generate the runtime manifest
    * CI checks
    * a future IDE / GUI tooling

5. Provide an extensive **diagnostics chain** (doctor) with structured error codes and suggested fixes.

### 1.2 Non-Goals

* The Packer **does not**:

    * generate `cartridge/manifest.json`
    * decide preload slots
    * copy files into `cartridge/`
    * compile PBS bytecode
    * zip cartridges

These responsibilities belong to a separate **Cartridge Shipper**.

---

## 2. Repository / Project Layout (Golden Pipeline)

The Prometeu project uses the following canonical structure:

* `src/` — PBS scripts
* `assets/` — mutable asset workspace (WIP allowed)
* `build/` — generated artifacts and caches
* `cartridge/` — final cartridge directory (produced by Cartridge Shipper)
* `prometeu.json` — project description (dependencies, version, etc.)
* `sdk/` — SDK/tooling and libraries

The Packer owns the asset workspace metadata under:

* `assets/.prometeu/` — Packer control directory (registry, cache, quarantine)

---

## 3. Crate Topology

### 3.1 Crates

* **`prometeu-packer`**

    * **lib**: `prometeu_packer_core`
    * **bin**: `prometeu-packer`

        * a thin CLI wrapper delegating to `prometeu_packer_core::run()`

* **`prometeu` dispatcher**

    * provides a wrapper command **`prometeup`** (or integrated subcommand)
    * delegates to `prometeu-packer` for packer operations

### 3.2 Design Principle

Treat the Packer like the compiler: core library + CLI wrapper.

* The core library enables future integrations (IDE, GUI, watch mode) without shelling out.
* CLI is a stable interface for users and CI.

---

## 4. Mental Model: A “Git-like” Asset Workspace

The Packer treats `assets/` like a **dirty working tree**.

* `assets/` can contain *anything*.
* Only the assets registered in the Packer registry are considered part of the build.

This is analogous to Git:

* working tree (chaos) vs index (truth)

The **source of truth** for “what counts” is the registry:

* `assets/.prometeu/index.json`

---

## 5. Core Concepts

### 5.1 Managed Asset

A **managed asset** is an entry in `assets/.prometeu/index.json` pointing to an **asset root directory** that contains an anchor file:

* `asset.json` (the asset specification)

Everything else is free-form.

### 5.2 Asset Identity

Each asset has stable identity:

* `asset_id: u32` — stable within the project (used by runtime/tooling)
* `asset_uuid: string` — globally unique stable identifier (useful for IDE and future migrations)

Names and paths may change, but identity remains.

### 5.3 Asset Types (Bank Targets)

Assets ultimately target a **bank type** in the runtime:

* `TILES`
* `SOUNDS`
* (future) `SPRITESHEET`, `MAP`, `FONT`, `RAW_BLOB`, etc.

The Packer does **not** define bank memory semantics. It defines the *ROM payload* and its metadata.

### 5.4 Raw vs Virtual Assets

* **Raw assets**: ROM payload equals the source bytes.
* **Virtual assets**: ROM payload is derived from input(s) via deterministic build steps.

Examples:

* PNG + palette files → `TILES` payload (indexed pixels + packed palettes)
* WAV → PCM16LE payload
* Multiple PNGs → atlas spritesheet

---

## 6. Directory Structure and Control Files

### 6.1 Workspace

`assets/` is a mutable workspace:

* users may create nested organization trees
* junk files are allowed

### 6.2 Control Directory

The Packer stores its truth + tools state in:

```
assets/
  .prometeu/
    index.json
    cache/
      fingerprints.json
      build-cache.json
    quarantine/
      ...
```

* `index.json` — registry of managed assets
* `cache/` — fingerprints and incremental build cache
* `quarantine/` — optional area to move detected junk (only by explicit user action)

---

## 7. Asset Specification: `asset.json`

`asset.json` describes:

1. **the output ROM payload** expected by runtime
2. **the build pipeline** (for virtual assets)
3. **metadata** needed by runtime/shipper

This spec is modular: **each asset format** (e.g. `TILES/indexed_v1`) has its own dedicated specification document.

### 7.1 Common Fields (All Assets)

* `schema_version`
* `name`
* `type` (bank type)
* `codec` (e.g. `RAW`; future: compression)
* `inputs` (for virtual assets)
* `output` (format + required metadata)
* `build` (optional pipeline configuration)

### 7.2 Virtual Asset Pipeline Declaration

Virtual assets must be declared in a way that is:

* deterministic
* fully materialized (no silent inference)
* explicit about defaults (defaults may exist, but must be written into `asset.json` or build outputs)

---

## 8. Build Artifacts Produced by the Packer

### 8.1 `build/assets.pa`

**`assets.pa`** is the ROM asset payload used by the runtime.

**Definition:** a contiguous binary blob where each managed asset contributes a payload region.

#### Key Properties

* Deterministic asset order (by `asset_id`)
* Offsets are recorded in `build/asset_table.json`
* Alignment rules (configurable by packer, default: no alignment unless required by a format)

**Note:** `assets.pa` is intentionally simple.

* No internal header is required.
* The authoritative structure comes from the descriptor (`asset_table.json`).

Future versions may introduce chunk tables, but v1 keeps ROM simple.

### 8.2 `build/asset_table.json`

**`asset_table.json`** is the canonical descriptor output of the Packer.

It contains:

* `assets_pa` file info (size, hash)
* `asset_table[]` entries describing each payload slice
* optional diagnostics/warnings

#### Asset Table Entry

An entry describes a ROM slice and its runtime meaning:

* `asset_id` — stable u32
* `asset_uuid` — stable UUID string
* `asset_name` — stable user-facing name
* `bank_type` — e.g. `TILES`, `SOUNDS`
* `offset` — byte offset in `assets.pa`
* `size` — bytes stored in ROM
* `decoded_size` — bytes after decode (equal to `size` when `codec=RAW`)
* `codec` — `RAW` (future: compression)
* `metadata` — format-specific metadata needed by runtime/shipper

Additional tooling fields:

* `source_root` — path to asset dir
* `inputs` — resolved input paths
* `source_hashes` — stable fingerprints of inputs

`asset_table.json` is machine-readable and designed for:

* cartridge shipper consumption
* IDE visualization
* debugging

---

## 9. Determinism Rules

1. Asset packing order MUST be deterministic.

    * Default: increasing `asset_id`

2. All derived outputs MUST be deterministic.

    * No random seeds unless explicitly declared
    * Any seed must be written to output metadata

3. Default values MUST be materialized.

    * If the packer infers something, it must be written into `asset.json` (via `--fix`) or recorded in build outputs.

---

## 10. Diagnostics and the “Sanity Guardian” Chain

The Packer provides structured diagnostics:

* `code` — stable diagnostic code
* `severity` — `error | warning | info`
* `path` — affected file
* `message` — human friendly
* `help` — extended context
* `fixes[]` — suggested automated or manual fixes

### 10.1 Diagnostic Classes

1. **Registered Errors** (break build)

    * registry entry missing anchor file
    * `asset.json` invalid
    * missing inputs
    * format/metadata mismatch

2. **Workspace Warnings** (does not break build)

    * orphaned `asset.json` (not registered)
    * unused large files
    * duplicate inputs by hash

3. **Policy Hints** (optional)

    * naming conventions
    * missing preview

### 10.2 `doctor` Modes

* `doctor` (default) — validate registry only (fast)
* `doctor --workspace` — deep scan workspace (slow)

---

## 11. Incremental Build, Cache, and Fingerprints

The Packer maintains fingerprints of inputs:

* size
* mtime
* strong hash (sha256)

Stored in:

* `assets/.prometeu/cache/fingerprints.json`

This enables:

* detecting changes
* rebuild only what changed
* producing stable reports

The cache must never compromise determinism.

---

## 12. Quarantine and Garbage Collection

### 12.1 Quarantine

The Packer can optionally move suspected junk to:

* `assets/.prometeu/quarantine/`

Rules:

* Quarantine is **never automatic** without user consent.
* Packer must explain exactly what will be moved.

### 12.2 Garbage Collection (`gc`)

The Packer can report unused files:

* files not referenced by any registered asset
* orphaned asset dirs

Actions:

* list candidates
* optionally move to quarantine
* never delete without explicit user request

---

## 13. CLI Commands (Comprehensive)

> The CLI is a stable interface; all commands are implemented by calling `prometeu_packer_core`.

### 13.1 `prometeu packer init`

Creates the control directory and initial registry:

* creates `assets/.prometeu/index.json`
* creates caches directory

### 13.2 `prometeu packer add <path> [--name <name>] [--type <TILES|SOUNDS|...>]`

Registers a new managed asset.

* does not require moving files
* can create an asset root directory if desired
* generates `asset.json` with explicit defaults
* allocates `asset_id` and `asset_uuid`

Variants:

* `add --dir` creates a dedicated asset root dir
* `add --in-place` anchors next to the file

### 13.3 `prometeu packer forget <name|id|uuid>`

Removes an asset from the registry without deleting files.

Useful for WIP and cleanup.

### 13.4 `prometeu packer rm <name|id|uuid> [--delete]`

Removes the asset from the registry.

* default: no deletion
* `--delete` can remove the asset root dir (dangerous; must confirm in UI tooling, or require a force flag in CLI)

### 13.5 `prometeu packer list`

Lists managed assets:

* id, uuid, name
* type
* status (ok/error)

### 13.7 `prometeu packer show <name|id|uuid>`

Shows detailed information:

* resolved inputs
* metadata
* fingerprints
* last build summary

### 13.8 `prometeu packer doctor [--workspace] [--strict] [--fix]`

Runs diagnostics:

* `--workspace` deep scan
* `--strict` warnings become errors
* `--fix` applies safe automatic fixes (materialize defaults, normalize paths)

### 13.9 `prometeu packer build [--out build/assets.pa] [--table build/asset_table.json]`

Builds:

* `build/assets.pa`
* `build/asset_table.json`

Key behaviors:

* validates registry before packing
* packs assets deterministically
* for virtual assets, runs build pipelines
* records all offsets and metadata

### 13.10 `prometeu packer watch`

Watches registered inputs and registry changes.

* emits events (future)
* rebuilds incrementally

`watch` is optional in v0 but recommended.

### 13.11 `prometeu packer gc [--workspace] [--quarantine]`

Reports unused files.

* default: report only
* `--quarantine` moves candidates to quarantine

### 13.12 `prometeu packer quarantine <path> [--restore]`

Moves or restores files into/from quarantine.

---

## 14. Virtual Assets (Deep Explanation)

Virtual assets are a major capability.

### 14.1 Why Virtual Assets

* Most runtime formats should be derived from human-friendly authoring formats.
* Example:

    * author uses `source.png` and palette files
    * runtime expects indexed pixels + packed RGB565 palettes

### 14.2 Virtual Asset Contract

* Inputs are explicit.
* Build steps are deterministic.
* Outputs match a well-defined runtime payload format.

### 14.3 Examples of Future Virtual Assets

* `TILES/indexed_v1`: PNG + palette files → indexed pixels + packed palettes
* `SOUNDS/pcm16le_v1`: WAV → PCM16LE
* `SPRITESHEET/atlas_v1`: multiple PNG frames → atlas + metadata

Each `output.format` must have its own dedicated spec.

---

## 15. Integration with Cartridge Shipper

The Cartridge Shipper should:

1. Compile PBS into bytecode (e.g. `program.pbc` / `program.pbx`)
2. Call `prometeu packer build`
3. Consume `build/asset_table.json` and produce `cartridge/manifest.json`
4. Copy artifacts into `cartridge/`
5. Zip the cartridge into a distributable format (`.crt` / `.rom` / `.pro`)

The packer never touches `cartridge/`.

---

## 16. Compatibility and Versioning

* `assets/.prometeu/index.json` has `schema_version`
* `asset.json` has `schema_version`
* `build/asset_table.json` has `schema_version`

The Packer must be able to migrate older schema versions or emit actionable diagnostics.

---

## 17. Security and Trust Model

* The Packer is offline tooling.
* It must never execute untrusted scripts.
* It should treat external inputs as untrusted data.

---

## 18. Implementation Notes (Non-Normative)

* Rust implementation with a core crate + CLI wrapper.
* Prefer structured JSON serde models.
* Use stable diagnostic codes.
* Keep the build deterministic.

---

## Appendix A — Glossary

* **ROM (`assets.pa`)**: packed asset payload used by runtime
* **Descriptor (`asset_table.json`)**: mapping from logical assets to ROM slices
* **Managed asset**: registered asset with stable identity and anchor file
* **Virtual asset**: derived asset built from multiple inputs
* **Quarantine**: safe area for suspected junk
* **Doctor**: diagnostic command to keep sanity
