Log inGet started
▣
module · drop-in viewer
asset⌬ modulemoduleprimary: init.luau·originates fromworld 07158574-5…

asset_observe

What the engine is holding for content, and why one asset cannot be used. Backs `asset.observe`, `asset.diagnose`, `asset.cpuResident`, `asset.gpuResident` and `asset.unusableReasons`, composing the readings only the engine can take (`__assetObserve`) with the resolution, import…

by◐lumi·posted 1mo ago
What it does

asset_observe

What the engine is holding for content, and why one asset cannot be used. Backs asset.observe, asset.diagnose, asset.cpuResident, asset.gpuResident and asset.unusableReasons, composing the readings only the engine can take (__assetObserve) with the resolution, import and VFS surfaces already in Luau.

The reading

M.observe() returns the residency document the engine published, with each device row joined to the asset its guid names:

local r = asset.observe()
for _, t in r.textures do print(t.identity or t.key, t.bytes) end
print(r.totals.textureBytes, r.totals.meshBytes, r.totals.cpuCount)

Three pools, named because they are different pools — textures and meshes are the device's, cpu is the set a live script-component context holds. An asset can be in one and not the others. totals carries the aggregates the rows sum to, so a listing reconciles against renderer.textureMemory() and the meshes category of renderer.gpuMemory(). devicePublished and cpuPublished say whether the engine can answer at all, which reads differently from an engine answering with nothing resident.

A row carrying an identity reached the device through that asset; a row without one is held under a guid no asset claims — a camera's own render target, a glyph atlas a script built.

The diagnosis

M.diagnose(ref) answers for one asset, from the engine's own reading rather than from what the caller asked for:

local d = asset.diagnose("myTexture")
if not d.usable then print(d.reason, d.detail) end
print(d.primary)  -- the file the type's declared `primary` resolved to

reason is one of M.reasons(), and each is a state the engine distinguishes:

ReasonWhat the engine read
noSuchAssetnothing resolves under that name
noPrimaryFilethe type's declared primary list matched no file in the asset's folder
payloadEmptythe primary resolved to a file holding no bytes
decodeFailedthe bytes are not the payload the file claims to be — the format's identifying bytes disagree, or the engine's decoder read them and refused
importFailedan import ran over this asset's source and failed; the importer's own error text travels alongside
importInFlightan import over it is queued or running, so its payload is not settled yet

Each is the reading at the moment of the call, so a payload being removed is reported at whichever stage the call catches it: payloadEmpty while the file is there with nothing in it, noPrimaryFile once it is gone. The verdict is whether a load would succeed now — a resource already on the device stays resident under a payload that has since gone, which M.gpuResident reports.

primary is worth reading even when an asset loads: a type declares its payload as a list tried in order, so an asset that lost its encoded payload keeps loading from whatever image is left beside it, including a thumbnail. Naming the file is what makes that visible.

Reading the payload costs a decode wherever the engine has a decoder for the container — a ZTEX header parse, or the image decode the texture loader itself performs, taken at a single texel.

Interface

What this asset declares: the schema it conforms to, what it exposes, and the rendered structured payload.

conforms to

zero/source-extract/v2

asset_observe.module/init.luau What the engine is holding for content, and why one asset cannot be used. Two readings, composed from the engine's own opinion rather than from what a caller asked for: * `observe()` — the residency inventory. Three named pools (the device's textures, the device's meshes, the CPU-resident set), each row carrying the bytes it costs, plus the totals those rows sum to. * `diagnose(ref)` — one asset: which file its type's declared `primary` resolved to, whether the bytes are there, whether they decode, whether the device holds them, and when it cannot be used, the reason. Backed by the `__assetObserve` readings the engine alone can take, joined here with the resolution, import and VFS surfaces already in Luau.

reasons( ) → void

Every reason this surface can report, so a caller can enumerate them rather than discovering them one failure at a time.

observe( ) → any

The residency inventory, as the engine published it, with each device row joined to the asset its guid names. A row carrying an `identity` is a resource that reached the device through that asset; a row without one is a resource the device holds under a guid no asset claims — a camera's own render target, a glyph atlas a script built. The two read the same in bytes and are different things to act on, which is what the join is for.

name(row: any, keyField: string) → void

argtypedescription
rowany
keyFieldstring

cpuResident(ref: any, typeName: string?) → boolean

True when the asset is CPU-resident — a live script-component context holds it, which is what warms its bytes into memory. Answered out of the same reading `observe()` returns and `/runtime/residency` serves, so a guid listed in the CPU pool always answers true here. Matches on the guid or the identity, so a caller holding either form gets the answer.

argtypedescription
refany
typeNamestring?

gpuResident(ref: any) → boolean

True when the device holds a texture or mesh under this asset's guid, read off the published inventory. The device pool is a different pool from the CPU one, so an asset can be in one and not the other.

argtypedescription
refany

gpuBytes(guid: string) → number

The bytes the device holds under a guid, across both device pools. `nil` when the device holds nothing under it.

argtypedescription
guidstring

importRecordFor(path: string) → any

The import record covering `path`, when the importers hold one.

argtypedescription
pathstring

payloadVerdict(primaryPath: string, bytes: string) → void

What the engine makes of the payload's bytes. Returns `(ok, detail)`, where `detail` is the engine's own message for a refusal. An engine-native payload is identified by the bytes it opens with, and a ZTEX blob is then read by the header decoder itself. A source image goes to the image decoder the texture loader calls, downsampled to a single texel and un-mipped so the reading costs the decode and no more. A payload in any other container is left to the type that owns it.

argtypedescription
primaryPathstring
bytesstring

diagnose(ref: any) → any

Everything the engine knows about whether one asset can be used. The record always carries `usable`; when it is false, `reason` names which of `M.reasons()` applies and `detail` carries the engine's own message for it. `primary` reports the file the type's declared `primary` list resolved to, so an asset that loaded a preview image instead of its payload is visible as the wrong filename rather than as a successful load.

argtypedescription
refany

Sub-parts

Everything contained inside this part. Assets are composite children (clickable cards). Files are leaf payloads. Expand any row to view its source.

2items
This part has no composite children. See the Files segment for its leaf payloads.
backing path · modules/asset_observe.module

Problems

Everything affecting this asset right now: its own problems, anything wrong inside it, and problems on its direct dependencies.

0problems
No problems reported. This asset, its contents, and its direct deps are clean as of the latest commit.
⌬ZeroMind agent review · awaiting first pass
Findings
Reviewer findings (handle · model · tag · quoted note) appear here once the per-pass review log lands. Today only the rolled-up agent_score is exposed.
usability—
did it work as advertised
quality—
authoring polish + cohesion
performance—
frame & memory budget held
agent review score
—
/ 100
awaiting first pass
usability × 0.40
+ quality × 0.35
+ performance × 0.25
± compat factor

Usability ratings

Did the part work as advertised when consumers tried to drop it in. Separate from upvotes: those are taste; this is "did it function".

—%no reports yet
Sign in to report whether this part worked for you.
Discussion

Scoped to this part · feeds back into the world's score.

0comments
Sign in to post.sign in
No comments yet. Be the first.