Reach the street-object placeholder spawn path headlessly with --placeholder kind=path #310
Labels
No labels
agent
agent:ci
agent:done
agent:failed
agent:needs-input
agent:refined
agent:refining
agent:running
agent:shipped
agent:skip
autonomous
autopilot
driven
local
plan
proposal
qa
qa-gap
research
retro
ship
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
jeroen/cartopolis#310
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Problem
The placeholder feature lets an operator replace built-in street objects (lamppost, bench, parked car and so on) with a model from the library. The step that places those models has never run.
docs/notes/street-objects-can-wear-a-model.md(section "Unverified") says: "the geometry half —build_furniture_meshes_except, the mask, the queue — is unit-tested, and the spawn path is not". It also names the next step: "a--placeholder kind=<file.glb>flag reading a local file through the ordinaryAssetServer".Two things stop a scripted capture from running that step today:
crates/cartopolis/src/systems/map/placeholder_models.rs:160poll_placeholdersfetches/api/library/placeholders, and whenmodel_assets::have_endpoint()is false it clears the table (models.adopt(Vec::new()), around line 186). Every scripted run is offline, so a seeded table would be wiped the next frame.spawn_placeholder_models(line 249) always loadsmodel_assets::asset_path(&hash), i.e.sim://{hash}.glb, which needs a server session.The harness also cannot see the spawn queue. No
ShotMetricsfield counts queued or spawned placeholder instances, so a capture can reportsettled=truewith the queue still draining atMAX_SPAWNS_PER_FRAME(64 per frame).Evidence
docs/notes/street-objects-can-wear-a-model.md, section "Unverified" (quoted above).placeholder_models.rs:160-205: the fetch and the offline clear.:249-300: the spawn, which always usesasset_path(hash).map_geometry.rs:2582-2612: the enqueue step, which is fed only bystores.placeholdersfor the forms in its mask.map_geometry.rs:2363: the mask goes intoDetailWants.modelled.map_geometry.rs:1756:build_furniture_meshes_exceptskips those forms when meshing.grepfinds noplaceholderfield incrates/cartopolis/src/systems/dev/shot_harness.rs.Approach
Placeholdergets a source that is either a library hash (as today) or a local asset path.spawn_placeholder_modelsloadsGltfAssetLabel::Scene(0).from_asset(...)from whichever it holds.--placeholder KIND=PATH[,scale=S][,yaw=DEG], repeatable.KINDis checked withFurnitureKind::from_slug, and an unknown slug is a startup error (same rule as unknown manifest and--expectkeys). The flag seedsPlaceholderModelsat startup and marks it local, sopoll_placeholdersneither fetches nor clears it. Scripted runs only: the table is world-wide by design, and a user-facing local override would contradict the module's first property.ShotMetrics:placeholder_spawned(live instances) andplaceholder_queued(queue length). Putplaceholder_queued > 0in the harness's busy list so a capture does not settle mid-drain.assets/models/avatar/characters/(e.g.Man_Casual.gltf), so no new binary goes into LFS.Acceptance criteria
--placeholder bench=models/x.gltf,scale=0.5,yaw=90gives the right kind, path, scale and angle in radians. An unknown kind is an error.poll_placeholderswith no endpoint leaves the table and its mask alone.placeholder_spawnedandplaceholder_queuedappear in--dump-stateand--csv, and asserting them with--expectis accepted.--placeholderfor a form the default vector tiles place there (bench or waste basket), exits 0 with--expect 'settled==true' --expect 'placeholder_spawned>0' --expect 'placeholder_queued==0'.placeholder_spawned==0.docs/notes/street-objects-can-wear-a-model.mdis updated with the measured count and the command that produced it.cargo test --locked --workspace --exclude cartopolis_androidpasses.Verification
This only checks geometry and counts, so the software rasteriser on the container is enough.
Out of scope
/api/library/placeholders, the wire or the schema.street_detail) that do not go throughmap_geometry's enqueue step.Direction
Serves value 6 (the feature becomes checkable by counts in
--dump-stateand--expectgates instead of by looking) and value 7 (the note's "Unverified" section is replaced with a measured count). It touches no wire protocol, no database schema, nothing that has to be looked at to judge, no AR, no Android publishing and no host.Filed unattended by the steward from
e4fae5dbe6. To reject, close it with a sentence saying why — the next run reads that.