Skip to content

Compile deterministic spriteset catalogs and bounded visual-resource packs #16

Description

@zoeyrose

Parent: atrinik/atrinik#314

Consumes content#61 and coordinates with content-toolkit#4, content-toolkit#6, content-toolkit#7, content#44, protocol#10, client#32, resources#14, renderer#6, and renderer#14.

Outcome

Specify and implement a deterministic, bounded compiler that turns validated visual-resource identities and logical spritesets into language-neutral catalogs and content-addressed transfer packs.

The compiler owns logical-to-physical planning and reproducible artifact construction. It does not own authored semantics, network transport, client cache policy, server scheduling, or GPU atlas residency.

Artifact model

Keep the following identities independent and versioned:

  • a resource member: stable ID, encoded-byte digest/size/type/dimensions, source/revision, distribution class, and license/notice reference;
  • a logical spriteset: stable ID, ordered/role-qualified resource dependencies, facings/timing or other presentation metadata, and optional affinity weight;
  • a physical pack: compiler algorithm/version, ordered member index, encoded/expanded bounds, complete digest, dependency packs, and compatibility features; and
  • a release manifest: exact content/toolkit/schema/source coordinates and the complete authenticated catalog/pack graph.

ABIN/AMAP remain bounded gameplay/content artifacts under content-toolkit#6. Large encoded media bytes should remain separately addressable pack members rather than being hidden inside ABIN/AMAP or raw Protobuf hashes.

Grouping and partitioning

  • Treat complete bounded animation/facing dependencies and required multipart/overlay resources as hard grouping or prefetch edges.
  • Treat explicit monster/tile/UI/effect families and measured map/region co-use as soft affinity. Preserve the reason/source of every edge in a debug/report artifact.
  • Recognize globally shared resources. Faces such as placeholders used by hundreds of animations belong in a common dependency pack instead of being copied into every set.
  • Give each encoded resource one physical home per release by default while allowing multiple logical-set memberships. Any deliberate duplication requires a reported latency/size benefit and retains each logical identity and attribution.
  • Enforce configurable maximum encoded bytes, expanded bytes, members, index bytes, dependencies, and set fan-out. Split oversized sets deterministically and retain ordered dependency/prefetch semantics.
  • Use a stable partitioning strategy so adding or changing one resource does not reshuffle unrelated packs. Emit clean-versus-incremental convergence and release-to-release churn reports.
  • Assign priority/prefetch classes as bounded hints for protocol/client consumers; never encode gameplay authority or hidden server state.

Container decision

Benchmark at least loose content-addressed blobs, stored ZIP, compressed ZIP, an indexed tar/compression variant, and a small purpose-built indexed container on the complete admitted corpus and representative changes.

Compare:

  • manifest/request overhead and cold-transfer bytes;
  • deterministic byte-for-byte construction on supported platforms;
  • member/range access and time to the first usable sprite/set;
  • incremental rebuild and update-amplification behavior;
  • decompression CPU/memory and already-compressed PNG behavior;
  • bounded parsing, traversal/link rejection, duplicate-name behavior, checksums, truncation/corruption handling, and compression-bomb exposure; and
  • Rust, Go, CDN/range, cache, and release-tool implementation complexity.

Select and version the simplest format that meets approved numeric budgets. ZIP is an option, not a requirement, and no consumer may perform ambient general-purpose extraction into a trusted filesystem tree.

APIs, schemas, and fixtures

  • Add headless Rust library APIs and atrinik-content CLI commands with explicit input/output roots, dry-run/plan output where publication would change artifacts, bounded machine-readable diagnostics, and atomic publication.
  • Publish versioned language-neutral schemas/specifications for the resource, spriteset, pack-index, and release-manifest artifacts.
  • Provide golden and negative fixtures for independent Go/Rust consumers. Include shared resources, multiple set membership, repeated animation frames, set splitting, aliases, zero-length/duplicate/overlapping members, bad offsets/digests/types/dimensions, missing dependencies, unsupported features, truncation, excessive expansion, and corruption.
  • Preserve exact license/notice references per member and in aggregate inventories. Refuse any distributable pack whose members are missing required ownership/attribution evidence.
  • Keep renderer-specific UV rectangles, page dimensions, padding/extrusion, texture format, mip policy, and residency out of the transfer-pack identity. A renderer may construct or consume atlas pages later through renderer#6/feat: publish granted content contracts #14.

Acceptance criteria

  • Identical validated inputs, compiler version, policy, and target profile produce byte-identical catalogs, indexes, packs, checksums, and reports across repeated supported clean builds.
  • Incremental and clean builds converge exactly; changing one face, animation, or family invalidates only the deterministic dependency closure and stays within an approved pack-churn budget.
  • The current corpus compiles with complete animation/facing sets and without duplicating heavily shared placeholders into every dependent set.
  • Every count, byte size, offset/range, expansion ratio, dependency, work queue, diagnostic, and output is bounded before allocation or publication.
  • Rust reference readers and independent Go/Rust fixture consumers reject all malformed/oversized/corrupt cases without partial publication, path traversal, executable content, or unbounded work.
  • The chosen container decision includes reproducible measurements for cold install, new-region traversal, warm cache, interrupted/resumed transfer, and representative one-asset changes rather than assuming archive compression helps PNG data.
  • content@main and resources can publish compatible artifacts through content#44/resources#14 without vendoring the toolkit or requiring sibling source checkouts; mixed-license bytes keep exact notices.
  • Client/server/renderer consumers use stable logical IDs and authenticated member/pack claims and remain correct if pack boundaries change between releases.
  • tools/validate.sh and git diff --check pass, including release consumer smoke tests and deterministic generation checks.

Dependencies and licensing

Depends on the toolkit catalog/schema foundations and content#61. Protocol/client/server work can proceed against small released fixtures once the artifact contract freezes; whole-corpus performance and convergence evidence also feeds content-toolkit#9.

Toolkit code/specifications/tests are fresh MIT work. Authored media and fixtures retain their actual licenses. Do not copy or translate the GPL Classic collector/container implementation unless an exact file-level approved provenance grant permits it.

Priority, blockers, and parallel delivery

Priority: P1 replacement critical-path producer. Start format/specification and synthetic-fixture work during P0; complete real-corpus compilation only after the catalog inputs freeze.

Hard completion blockers

  • content-toolkit#4 must expose the stable catalog/query/diagnostic foundation used by the compiler.
  • content#61 must publish the versioned face/animation/family identity, reference, distribution, and notice contract.

These block whole-corpus completion, not the ADR, artifact schemas, synthetic fixtures, bounds, partition prototype, or negative readers. content-toolkit#6 is a coordinated ABIN/AMAP sibling rather than a blocker to the standalone media pack compiler. content-toolkit#7 is the release/consumer handoff needed before downstream repositories consume the result without sibling checkouts.

Execution order

Phase Work Parallel work Gate/handoff
T0 — ADR and fixture-first contract Define resource/spriteset/pack/release concepts, exact canonical digest inputs, bounds, compatibility/features, and one small licensed positive/negative fixture. Container benchmark harness, hostile index corpus, language-neutral schema, Rust reference reader Protocol#10/server#76/client#32 can begin against immutable fixture v0
T1 — deterministic planning core Implement stable grouping/partitioning, shared-member dependencies, size caps/splitting, canonical indexes, clean/incremental convergence, and churn reports on synthetic catalogs. Partitioner, index writer/reader, property tests, cross-platform determinism, metrics/report schema No filesystem/map order affects outputs; malformed inputs fail before publication
T2 — catalog integration Consume content-toolkit#4 plus content#61; compile the complete supported external corpus without embedding unlicensed bytes in MIT fixtures/releases. Domain adapter, source-span/debug manifest, admission filtering, whole-corpus performance Complete catalog closure and member-scoped license/distribution decisions
T3 — choose and freeze the container Run the full ADR matrix, approve numeric transfer/churn/random-access/decompression budgets, select/version the simplest qualifying container, and freeze pack/index feature negotiation. ZIP/indexed/solid/loose prototypes may run concurrently behind the same benchmark Physical format is fixed only after evidence; logical IDs remain unchanged if it changes later
T4 — release and consumers Publish schemas, crates/CLI, fixtures, specs, checksums, and smoke projects through content-toolkit#7; coordinate content#44/resources#14. Go reader/service and Rust client/provider conformance can run in parallel against release candidates Downstream builds require released artifacts, not path/source overrides

Parallel workstreams

  • Artifact contract: schemas, canonical encoding/digests, compatibility, bounds, and reference reader.
  • Packing algorithm: hard/soft edges, deterministic splits, common packs, deduplication, incremental stability, and churn reports.
  • Security/conformance: hostile index/container fixtures, path/link rejection, expansion/allocation limits, fuzz/property tests, and independent Go/Rust readers.
  • Benchmark/ADR: request overhead, encoded bytes, time-to-first-set, update amplification, CPU/memory/disk, and CDN/range behavior.
  • Release plumbing: content-toolkit#7 can prepare publishing, consumer smoke projects, and override contracts before T3 freezes the final feature set.

Consumer handoff order

  1. T0 fixture to protocol#10, server#76, client#32, and renderer#6 for interface development.
  2. T1/T2 release candidate to content#44/resources#14 for deterministic publication and license inventory validation.
  3. T4 immutable release to Go/Rust consumers and wrapper profiles.
  4. Whole-corpus convergence/performance evidence to content-toolkit#9; Prove whole-corpus conversion, determinism, compatibility, and cache behavior #9 is downstream M4 validation, not a blocker to this M2 compiler.

This issue is complete only when the released artifact—not a workspace path—passes independent Go/Rust positive and negative consumer fixtures and the approved deterministic/churn budgets.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Fields

    Priority

    None yet

    Effort

    None yet

    Projects

    Status
    Inbox

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions