@aura3d/cli 1.4.5 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/dist/asset-intent.d.ts +148 -0
  2. package/dist/asset-intent.d.ts.map +1 -0
  3. package/dist/asset-intent.js +145 -0
  4. package/dist/asset-intent.js.map +1 -0
  5. package/dist/asset-role-admission.d.ts +174 -0
  6. package/dist/asset-role-admission.d.ts.map +1 -0
  7. package/dist/asset-role-admission.js +381 -0
  8. package/dist/asset-role-admission.js.map +1 -0
  9. package/dist/asset-screening-effects.d.ts +95 -0
  10. package/dist/asset-screening-effects.d.ts.map +1 -0
  11. package/dist/asset-screening-effects.js +321 -0
  12. package/dist/asset-screening-effects.js.map +1 -0
  13. package/dist/asset-screening-pipeline.d.ts +132 -0
  14. package/dist/asset-screening-pipeline.d.ts.map +1 -0
  15. package/dist/asset-screening-pipeline.js +277 -0
  16. package/dist/asset-screening-pipeline.js.map +1 -0
  17. package/dist/cartoon-asset-profiles.d.ts +15 -0
  18. package/dist/cartoon-asset-profiles.d.ts.map +1 -0
  19. package/dist/cartoon-asset-profiles.js +46 -0
  20. package/dist/cartoon-asset-profiles.js.map +1 -0
  21. package/dist/cli-help.js +1 -1
  22. package/dist/cli.js +16 -2
  23. package/dist/cli.js.map +1 -1
  24. package/dist/index.d.ts +8 -0
  25. package/dist/index.d.ts.map +1 -1
  26. package/dist/index.js +390 -17
  27. package/dist/index.js.map +1 -1
  28. package/dist/pull-bridge/search.d.ts +4 -0
  29. package/dist/pull-bridge/search.d.ts.map +1 -1
  30. package/dist/pull-bridge/search.js +22 -0
  31. package/dist/pull-bridge/search.js.map +1 -1
  32. package/dist/pull-bridge.d.ts +20 -5
  33. package/dist/pull-bridge.d.ts.map +1 -1
  34. package/dist/pull-bridge.js +38 -1
  35. package/dist/pull-bridge.js.map +1 -1
  36. package/package.json +3 -3
@@ -0,0 +1,381 @@
1
+ /**
2
+ * Role-aware asset fitness admission.
3
+ *
4
+ * ## Why this exists, and why one boolean is not enough
5
+ *
6
+ * Three hero-vehicle assets shipped into Turbo Drift Circuit and every one of them was visually wrong
7
+ * in a *different* way that every existing gate accepted:
8
+ *
9
+ * | Asset | Parts | Triangles | Actual failure |
10
+ * | --- | --- | --- | --- |
11
+ * | `showcaseTexturedSportsCar` | 7 | 33,700 | tyres attached through detached stalk-like geometry |
12
+ * | `showcaseCityVehicle` | 1 | 792 | a distant low-poly body shell with no wheels modelled at all |
13
+ * | `turboHeroCar` | 483 | 71,426 | closed-wheel Le Mans body encloses the wheels; not readable |
14
+ *
15
+ * Nothing caught them because every upstream check measured the *frame*, not the *model*: probe
16
+ * thresholds measure subject pixel size, readability rules measure foreground bounds, composition
17
+ * checks measure coverage ratios. A wheelless car is a large, well-lit, correctly-framed subject and
18
+ * passes all of them.
19
+ *
20
+ * The second lesson is that fitness is **not global**. `showcaseCityVehicle` is a perfectly good
21
+ * background traffic prop and a bad hero. `turboHeroCar` is a structurally valid vehicle and a bad
22
+ * choice when the requested style needs exposed tyres. Collapsing that into one pass/fail either
23
+ * rejects usable assets or admits unusable ones. So admission is evaluated **against a requested role
24
+ * and its visual requirements**, and every check is reported individually with its own verdict so a
25
+ * rejection is machine-readable and explains itself.
26
+ *
27
+ * ## Deliberate boundary
28
+ *
29
+ * This module is structural only. It consumes geometry and provenance facts and never claims rendered
30
+ * visibility: `wheelsVisibleInSilhouette` is a *geometric prediction* that wheels reach the body
31
+ * silhouette, not proof a viewer saw them. Rendered proof is a separate input
32
+ * (`renderedWheelVisibility`) supplied by a browser probe, because the repository rule is that no
33
+ * visual claim may rest on mesh statistics. When rendered evidence is absent for a role that requires
34
+ * it, admission reports `unproven` rather than `pass`.
35
+ */
36
+ /** Minimum distinct outboard corners for a vehicle to count as wheeled. */
37
+ export const MIN_VEHICLE_WHEEL_CORNERS = 3;
38
+ /** Below this triangle count an asset is a distant prop, not a hero subject. */
39
+ export const HERO_MIN_TRIANGLES = 3_000;
40
+ /**
41
+ * A hero render must cover at least this many distinct azimuths.
42
+ *
43
+ * One angle is not evidence: the `turboRaceCar` release probe rendered a dead-on front view (camera
44
+ * azimuth and node rotation cancelled exactly), which is the single angle where a car's own bodywork
45
+ * hides its wheels. That frame was read as "the renderer is dropping the wheel primitives" when in
46
+ * fact all five primitives were drawing. Requiring multiple angles makes that mistake impossible.
47
+ */
48
+ export const HERO_MIN_RENDERED_AZIMUTHS = 2;
49
+ /**
50
+ * Evaluate an asset against a requested role.
51
+ *
52
+ * Returns every check individually. Callers must not reduce this to a boolean without also surfacing
53
+ * `blockers` and `unproven`, or the "asset loads, therefore asset is fine" failure returns.
54
+ */
55
+ export function admitAssetForRole(input) {
56
+ const { requirement: requirement, geometry, rendered, provenance } = input;
57
+ const checks = [];
58
+ const isVehicle = requirement.role === "hero-vehicle" || requirement.role === "background-vehicle";
59
+ const isHero = requirement.role === "hero-vehicle" || requirement.role === "playable-character" || requirement.role === "ui-hero-object";
60
+ checks.push({
61
+ id: "part-count",
62
+ verdict: geometry.partCount > 0 ? "pass" : "fail",
63
+ detail: geometry.partCount > 0 ? `${geometry.partCount} mesh part(s)` : "no mesh parts with readable bounds",
64
+ measured: geometry.partCount
65
+ });
66
+ /*
67
+ * The hero triangle floor applies only when a triangle count was actually measured.
68
+ *
69
+ * Callers that read structural facts from a manifest have no triangle count available. Defaulting a
70
+ * missing count to `0` and then failing the floor reports "distant-prop shell" for *absent metadata*,
71
+ * which is a false accusation: it fired on correctly-certified release fixtures. A floor can only be
72
+ * enforced against a real measurement, so `triangles === 0` disables the implied hero floor while an
73
+ * explicitly requested `minTriangles` is still honoured.
74
+ */
75
+ const minTriangles = requirement.minTriangles ?? (isHero && geometry.triangles > 0 ? HERO_MIN_TRIANGLES : undefined);
76
+ if (minTriangles !== undefined) {
77
+ const ok = geometry.triangles >= minTriangles;
78
+ checks.push({
79
+ id: "triangle-floor",
80
+ verdict: ok ? "pass" : "fail",
81
+ detail: ok
82
+ ? `${geometry.triangles} triangles meets the ${minTriangles} floor for ${requirement.role}`
83
+ : `${geometry.triangles} triangles is below the ${minTriangles} floor for ${requirement.role}; this is a distant-prop shell, not a hero subject`,
84
+ measured: geometry.triangles
85
+ });
86
+ }
87
+ if (requirement.maxTriangles !== undefined) {
88
+ const ok = geometry.triangles <= requirement.maxTriangles;
89
+ checks.push({
90
+ id: "triangle-budget",
91
+ verdict: ok ? "pass" : "fail",
92
+ detail: ok
93
+ ? `${geometry.triangles} triangles within the ${requirement.maxTriangles} budget`
94
+ : `${geometry.triangles} triangles exceeds the ${requirement.maxTriangles} budget`,
95
+ measured: geometry.triangles
96
+ });
97
+ }
98
+ if (requirement.requireTextured) {
99
+ const textures = geometry.textureCount ?? 0;
100
+ checks.push({
101
+ id: "textured",
102
+ verdict: textures > 0 ? "pass" : "fail",
103
+ detail: textures > 0 ? `${textures} texture(s)` : "no textures; the role requires textured materials rather than flat colour",
104
+ measured: textures
105
+ });
106
+ }
107
+ if (isVehicle) {
108
+ const corners = geometry.distinctWheelCorners ?? 0;
109
+ const candidates = geometry.wheelCandidates ?? 0;
110
+ const wheeled = corners >= MIN_VEHICLE_WHEEL_CORNERS;
111
+ /*
112
+ * Distinguish "measured and absent" from "never measured".
113
+ *
114
+ * Wheel-part detection requires reading the mesh; a caller working from manifest metadata cannot
115
+ * supply it. Reporting `fail` in that case accused correctly-certified assets of having no wheels.
116
+ * `unproven` is the honest verdict when neither field was provided, and it still blocks admission --
117
+ * it simply does not claim the asset is wheelless.
118
+ */
119
+ const wheelGeometryMeasured = geometry.wheelCandidates !== undefined || geometry.distinctWheelCorners !== undefined;
120
+ checks.push({
121
+ id: "wheel-geometry-present",
122
+ verdict: wheeled ? "pass" : wheelGeometryMeasured ? "fail" : "unproven",
123
+ detail: wheeled
124
+ ? `${candidates} wheel-like part(s) across ${corners} corner(s)`
125
+ : !wheelGeometryMeasured
126
+ ? "wheel geometry was not measured; supply wheelCandidates/distinctWheelCorners from a mesh audit"
127
+ : candidates === 0
128
+ ? "no roughly-circular low-mounted parts: this is a body shell with no wheels modelled"
129
+ : `wheel-like parts at only ${corners} corner(s); a vehicle needs ${MIN_VEHICLE_WHEEL_CORNERS}+`,
130
+ measured: corners
131
+ });
132
+ // Deliberately separate from the check above: existence is not readability.
133
+ if (requirement.requireReadableWheels) {
134
+ const silhouette = geometry.wheelsVisibleInSilhouette;
135
+ checks.push({
136
+ id: "wheels-outside-body-silhouette",
137
+ verdict: silhouette === undefined ? "unproven" : silhouette ? "pass" : "fail",
138
+ detail: silhouette === undefined
139
+ ? "wheel/body silhouette relationship was not measured"
140
+ : silhouette
141
+ ? `wheels reach the body silhouette (wheel half-width ${fmt(geometry.wheelHalfWidth)} vs body ${fmt(geometry.bodyHalfWidth)})`
142
+ : `wheels are enclosed inside the bodywork (wheel half-width ${fmt(geometry.wheelHalfWidth)} vs body ${fmt(geometry.bodyHalfWidth)}); they exist but cannot be seen, so this reads as a closed-wheel prototype`,
143
+ measured: silhouette
144
+ });
145
+ // Structural prediction is never accepted as rendered proof.
146
+ const renderedVisible = rendered?.renderedWheelVisibility;
147
+ const azimuths = rendered?.renderedAzimuths?.length ?? 0;
148
+ if (renderedVisible === undefined) {
149
+ checks.push({
150
+ id: "rendered-wheel-visibility",
151
+ verdict: "unproven",
152
+ detail: "no retained render measures wheel visibility; geometry alone cannot prove a viewer sees the tyres",
153
+ measured: false
154
+ });
155
+ }
156
+ else if (!renderedVisible) {
157
+ checks.push({
158
+ id: "rendered-wheel-visibility",
159
+ verdict: "fail",
160
+ detail: `retained render${rendered?.screenshotPath ? ` ${rendered.screenshotPath}` : ""} does not show readable wheels`,
161
+ measured: false
162
+ });
163
+ }
164
+ else if (azimuths < HERO_MIN_RENDERED_AZIMUTHS) {
165
+ checks.push({
166
+ id: "rendered-wheel-visibility",
167
+ verdict: "unproven",
168
+ detail: `wheels read at only ${azimuths} camera angle(s); ${HERO_MIN_RENDERED_AZIMUTHS}+ are required because a single head-on view is the one angle where bodywork hides its own wheels`,
169
+ measured: azimuths
170
+ });
171
+ }
172
+ else {
173
+ checks.push({
174
+ id: "rendered-wheel-visibility",
175
+ verdict: "pass",
176
+ detail: `wheels read across ${azimuths} camera angles in ${rendered?.screenshotPath ?? "the retained render"}`,
177
+ measured: azimuths
178
+ });
179
+ }
180
+ }
181
+ if (geometry.detachedPartCount !== undefined && geometry.detachedPartCount > 0) {
182
+ checks.push({
183
+ id: "detached-geometry",
184
+ verdict: "fail",
185
+ detail: `${geometry.detachedPartCount} part(s) are detached from the body shell, which reads as components floating on stalks`,
186
+ measured: geometry.detachedPartCount
187
+ });
188
+ }
189
+ }
190
+ // Grounding confidence: an asset whose lowest point is far from its origin needs the normalization
191
+ // path to be exercised, and a caller should know that before trusting a placement.
192
+ if (geometry.minY !== undefined) {
193
+ const height = geometry.bounds[1];
194
+ const offsetRatio = height > 0 ? Math.abs(geometry.minY) / height : 0;
195
+ checks.push({
196
+ id: "grounding-offset",
197
+ verdict: "pass",
198
+ detail: offsetRatio <= 0.02
199
+ ? "lowest point sits effectively on the asset origin"
200
+ : `lowest point sits ${(offsetRatio * 100).toFixed(1)}% of asset height from the origin; placement must use the normalization path rather than the raw origin`,
201
+ measured: Number(offsetRatio.toFixed(4))
202
+ });
203
+ }
204
+ /*
205
+ * Normalization requirement, recorded as its own check rather than folded into grounding.
206
+ *
207
+ * These are different questions and were previously conflated in one message. Grounding asks "how far is the
208
+ * lowest point from the origin"; normalization asks "must a caller scale this asset to a target size, or are
209
+ * its units already scene-appropriate". `turboRaceCar` measures 186 x 176 x 378 units against a 1.1-unit
210
+ * target -- a 344x fit -- and a route that skipped the normalization path would place a car the size of the
211
+ * circuit. Reporting it separately means a caller can see the requirement without parsing prose.
212
+ */
213
+ {
214
+ const longest = Math.max(...geometry.bounds);
215
+ // Anything outside roughly scene-scale needs an explicit fit; 12 units is generous for a single subject.
216
+ const needsNormalization = longest > 12 || longest < 0.08;
217
+ checks.push({
218
+ id: "normalization-required",
219
+ verdict: "pass",
220
+ detail: needsNormalization
221
+ ? `longest axis is ${longest.toFixed(2)} units; placement must fit to a target size rather than use raw asset units`
222
+ : `longest axis is ${longest.toFixed(2)} units, already scene-scale`,
223
+ measured: Number(longest.toFixed(4))
224
+ });
225
+ }
226
+ /*
227
+ * Orientation evidence. Never inferred: a symmetric body has no intrinsic front, so a guess here becomes a car
228
+ * driving backwards down the track. Absent evidence is `unproven` unless the role demands it, in which case it
229
+ * is a `fail` -- the brief's "reject if required orientation evidence is absent".
230
+ */
231
+ {
232
+ const declared = geometry.forwardAxis;
233
+ const hasEvidence = Array.isArray(declared) && declared.some((component) => Math.abs(component) > 1e-6);
234
+ /*
235
+ * `not-applicable` when the role did not ask for orientation, not `unproven`.
236
+ *
237
+ * `unproven` forbids admission by design -- it is how "nobody measured whether the tyres are visible" stops
238
+ * being mistaken for "the tyres are visible". Reporting absent-but-unrequested orientation as `unproven`
239
+ * would therefore make *every* asset unadmissible, including a rock that has no meaningful forward axis. The
240
+ * distinction that matters is: the role asked and we cannot answer (`fail`), versus the role never asked
241
+ * (`not-applicable`). Both are recorded, so a reader sees the fact either way.
242
+ */
243
+ checks.push({
244
+ id: "orientation-evidence",
245
+ verdict: hasEvidence ? "pass" : requirement.requireOrientationEvidence ? "fail" : "not-applicable",
246
+ detail: hasEvidence
247
+ ? `manifest declares forward axis [${declared.join(", ")}]`
248
+ : requirement.requireOrientationEvidence
249
+ ? "no manifest forward axis; orientation cannot be inferred from geometry and must not be guessed"
250
+ : "no manifest forward axis; this role does not require one",
251
+ measured: hasEvidence ? declared.join(",") : false
252
+ });
253
+ }
254
+ /*
255
+ * Front/rear inference, kept distinct from orientation evidence.
256
+ *
257
+ * Orientation says *which way* the asset faces; this says whether front and rear are even distinguishable
258
+ * from its geometry. A perfectly symmetric shell can carry a declared forward axis and still read ambiguously
259
+ * to a viewer, which is a visual-fitness fact a hero role should surface.
260
+ */
261
+ if (geometry.frontRearDistinguishable !== undefined) {
262
+ checks.push({
263
+ id: "front-rear-inference",
264
+ // A reported visual-fitness fact, not a gate: `unproven` would block admission (see orientation above).
265
+ verdict: geometry.frontRearDistinguishable ? "pass" : "not-applicable",
266
+ detail: geometry.frontRearDistinguishable
267
+ ? "front and rear are geometrically distinguishable"
268
+ : "front and rear are not geometrically distinguishable; a viewer may not read the facing direction",
269
+ measured: geometry.frontRearDistinguishable
270
+ });
271
+ }
272
+ /*
273
+ * Origin/pivot sanity. An asset whose origin sits far from its bounds centre rotates around a point outside
274
+ * itself, so a route that spins it appears to swing it on a boom. Distinct from grounding, which is only
275
+ * about the vertical axis.
276
+ */
277
+ if (geometry.pivotOffsetRatio !== undefined) {
278
+ const sane = geometry.pivotOffsetRatio <= 0.35;
279
+ checks.push({
280
+ id: "origin-pivot-sanity",
281
+ verdict: sane ? "pass" : "fail",
282
+ detail: sane
283
+ ? `origin sits ${(geometry.pivotOffsetRatio * 100).toFixed(1)}% of the longest axis from the bounds centre`
284
+ : `origin sits ${(geometry.pivotOffsetRatio * 100).toFixed(1)}% of the longest axis from the bounds centre; rotation will swing the asset around a point outside itself`,
285
+ measured: Number(geometry.pivotOffsetRatio.toFixed(4))
286
+ });
287
+ }
288
+ /*
289
+ * Material completeness, distinct from the `textured` check.
290
+ *
291
+ * `textured` asks whether the asset uses textures at all. This asks whether every mesh part has a material
292
+ * assigned: a part with none has no shader to draw with and renders as an untextured default or not at all,
293
+ * which is one of the ways a "loads successfully" asset can still be visually broken.
294
+ */
295
+ if (geometry.partsWithoutMaterial !== undefined) {
296
+ const complete = geometry.partsWithoutMaterial === 0;
297
+ checks.push({
298
+ id: "material-completeness",
299
+ verdict: complete ? "pass" : "fail",
300
+ detail: complete
301
+ ? "every mesh part carries a material assignment"
302
+ : `${geometry.partsWithoutMaterial} mesh part(s) carry no material assignment and have no shader to draw with`,
303
+ measured: geometry.partsWithoutMaterial
304
+ });
305
+ }
306
+ if (requirement.requireProvenance) {
307
+ const complete = Boolean(provenance?.license && provenance?.author);
308
+ checks.push({
309
+ id: "provenance-complete",
310
+ verdict: complete ? "pass" : "fail",
311
+ detail: complete
312
+ ? `${provenance?.license} by ${provenance?.author}`
313
+ : `incomplete provenance (license: ${provenance?.license ?? "missing"}, author: ${provenance?.author ?? "missing"})`,
314
+ measured: complete
315
+ });
316
+ }
317
+ const blockers = checks
318
+ .filter((check) => check.verdict === "fail")
319
+ .map((check) => `${check.id}:${check.detail}`);
320
+ const unproven = checks
321
+ .filter((check) => check.verdict === "unproven")
322
+ .map((check) => `${check.id}:${check.detail}`);
323
+ return {
324
+ schema: "aura3d-asset-role-admission/1.0",
325
+ assetId: input.assetId,
326
+ role: requirement.role,
327
+ checks,
328
+ admitted: blockers.length === 0 && unproven.length === 0,
329
+ blockers,
330
+ unproven,
331
+ suitableAlternativeRoles: suggestAlternativeRoles(input, blockers.length > 0 || unproven.length > 0)
332
+ };
333
+ }
334
+ /**
335
+ * Suggest roles the asset would satisfy instead.
336
+ *
337
+ * This is what makes role-aware admission useful rather than merely stricter: rejecting
338
+ * `showcaseCityVehicle` as a hero is correct, but it is still a good background traffic prop, and a
339
+ * pipeline that only says "rejected" throws away that information.
340
+ */
341
+ function suggestAlternativeRoles(input, rejected) {
342
+ if (!rejected)
343
+ return [];
344
+ const roles = [];
345
+ const { geometry, requirement } = input;
346
+ const isVehicleRequest = requirement.role === "hero-vehicle" || requirement.role === "background-vehicle";
347
+ if (isVehicleRequest && requirement.role === "hero-vehicle" && geometry.partCount > 0) {
348
+ // A shell or an enclosed-wheel body still reads correctly at distance.
349
+ roles.push("background-vehicle");
350
+ }
351
+ if (geometry.partCount > 0 && geometry.triangles < HERO_MIN_TRIANGLES)
352
+ roles.push("prop");
353
+ return roles;
354
+ }
355
+ /**
356
+ * Rank candidates for a role, best first.
357
+ *
358
+ * Admitted candidates always outrank rejected ones; within each group, fewer blockers then fewer
359
+ * unproven checks then more triangles wins. Rejected candidates are **retained**, with their reasons,
360
+ * because a screening loop needs to report why every candidate failed rather than silently discarding
361
+ * them.
362
+ */
363
+ export function rankAssetCandidatesForRole(inputs) {
364
+ return inputs
365
+ .map((input) => admitAssetForRole(input))
366
+ .sort((a, b) => {
367
+ if (a.admitted !== b.admitted)
368
+ return a.admitted ? -1 : 1;
369
+ if (a.blockers.length !== b.blockers.length)
370
+ return a.blockers.length - b.blockers.length;
371
+ if (a.unproven.length !== b.unproven.length)
372
+ return a.unproven.length - b.unproven.length;
373
+ const aTriangles = inputs.find((input) => input.assetId === a.assetId)?.geometry.triangles ?? 0;
374
+ const bTriangles = inputs.find((input) => input.assetId === b.assetId)?.geometry.triangles ?? 0;
375
+ return bTriangles - aTriangles;
376
+ });
377
+ }
378
+ function fmt(value) {
379
+ return value === undefined ? "unknown" : value.toFixed(2);
380
+ }
381
+ //# sourceMappingURL=asset-role-admission.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"asset-role-admission.js","sourceRoot":"","sources":["../../../../packages/aura3d-cli/src/asset-role-admission.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Real bindings for the screening pipeline's injected effects.
3
+ *
4
+ * ## Why this file exists separately from the pipeline
5
+ *
6
+ * `asset-screening-pipeline.ts` owns *ordering and record-keeping* and takes every external effect as an
7
+ * injected function. That separation is what makes the part that historically failed -- running the steps
8
+ * in order and keeping every rejection reason -- testable offline. But an orchestrator with no real
9
+ * bindings is a library nobody can run: the previous state of this work had 38 passing tests against
10
+ * injected fakes and no way to actually screen a candidate.
11
+ *
12
+ * This module supplies the production wiring: catalog search, download, and structural geometry
13
+ * inspection read from the pulled file. It deliberately does **not** supply a render probe by default.
14
+ *
15
+ * ## Why no default render probe
16
+ *
17
+ * Rendering requires a browser (Playwright) and a dev server. Importing that here would make the CLI
18
+ * package depend on the test harness, and worse, it would tempt a caller into fabricating a "rendered"
19
+ * verdict from geometry when no browser is present. Omitting `renderProbe` means admission reports
20
+ * rendered visibility as `unproven` rather than passing -- the honest outcome, and the one the whole
21
+ * investigation was about. A caller with a working harness injects it explicitly.
22
+ */
23
+ import type { AssetGeometryFacts } from "./asset-role-admission.js";
24
+ import type { ScreeningEffects, ScreeningRenderCost } from "./asset-screening-pipeline.js";
25
+ export interface ScreeningEffectsOptions {
26
+ /** Repository/project root, used for durable staging when registering. */
27
+ readonly projectDir?: string | undefined;
28
+ /** Directory pulled candidates are downloaded into. Defaults to a fresh temp directory. */
29
+ readonly stagingDir?: string | undefined;
30
+ readonly env?: NodeJS.ProcessEnv | undefined;
31
+ /** Candidates requested per query. */
32
+ readonly searchLimit?: number | undefined;
33
+ /**
34
+ * Optional render probe. Supply one only when a real browser harness is available.
35
+ *
36
+ * When omitted, admission correctly reports rendered visibility as `unproven`.
37
+ *
38
+ * This is a capability boundary, not a gap: geometry must never stand in for a rendered verdict.
39
+ */
40
+ readonly renderProbe?: ScreeningEffects["renderProbe"] | undefined;
41
+ /** Optional registration step, so a screening run can end in a typed asset. */
42
+ readonly register?: ScreeningEffects["register"] | undefined;
43
+ }
44
+ /**
45
+ * Build production screening effects.
46
+ *
47
+ * Search failures propagate as thrown errors so the pipeline records them per query rather than treating
48
+ * an outage as "no candidates exist" -- a distinction that cost a whole pass when I concluded the catalog
49
+ * was empty without having searched it.
50
+ */
51
+ export declare function createScreeningEffects(options?: ScreeningEffectsOptions): ScreeningEffects;
52
+ /**
53
+ * Structural geometry facts read directly from a GLB.
54
+ *
55
+ * This is the same measurement the standalone auditor performs, expressed in the admission vocabulary. It
56
+ * reads accessor min/max composed through the node hierarchy rather than trusting any manifest metadata,
57
+ * because the whole point of screening is to judge a file that is not registered yet.
58
+ */
59
+ export declare function inspectGlbGeometry(file: string): AssetGeometryFacts & ScreeningRenderCost;
60
+ /** sha256 of a staged file, for provenance binding in a screening report. */
61
+ export declare function hashStagedFile(file: string): string;
62
+ /** Resolve a project-relative path, for callers staging into the repository. */
63
+ export declare function resolveProjectPath(projectDir: string | undefined, relativePath: string): string;
64
+ /**
65
+ * Build a render probe that reads a *retained* multi-angle visibility report.
66
+ *
67
+ * ## Why reading retained evidence is the right binding
68
+ *
69
+ * The alternative — launching a browser from inside the CLI — would make this package depend on the test
70
+ * harness and would put a 30-second render inside a search loop. Worse, a caller without a browser would be
71
+ * tempted to synthesise a verdict from geometry, which is the conflation that produced a false renderer
72
+ * diagnosis in the first place.
73
+ *
74
+ * Retained reports are produced by `tests/browser/vehicle-wheel-visibility.spec.ts`, which renders an asset
75
+ * across several azimuths and measures the lower-silhouette wheel band per angle. Reading them means the
76
+ * pipeline consumes *real rendered proof* while the rendering stays owned by the browser suite.
77
+ *
78
+ * A missing report is not treated as a failure: `renderedWheelVisibility` is left undefined so admission
79
+ * reports `unproven`. That distinction matters — "no evidence" and "evidence of absence" are different, and
80
+ * conflating them is what made a correctly-drawing asset look broken.
81
+ */
82
+ export declare function createRetainedRenderProbe(options?: {
83
+ /** Directory holding `<assetId>.json` visibility reports. */
84
+ readonly reportDir?: string | undefined;
85
+ readonly projectDir?: string | undefined;
86
+ /**
87
+ * Minimum band pixels for a wheel band to count as readable at an angle.
88
+ *
89
+ * Measured against the accepted hero: its readable angles carry >10k band pixels while a dead-on front
90
+ * view carries mass that is body, not tyre. The threshold is deliberately low and paired with the
91
+ * outer-third test below rather than being tuned to a single asset.
92
+ */
93
+ readonly minBandPixels?: number | undefined;
94
+ }): NonNullable<ScreeningEffects["renderProbe"]>;
95
+ //# sourceMappingURL=asset-screening-effects.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"asset-screening-effects.d.ts","sourceRoot":"","sources":["../../../../packages/aura3d-cli/src/asset-screening-effects.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAOH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,KAAK,EAEV,gBAAgB,EAEhB,mBAAmB,EACpB,MAAM,+BAA+B,CAAC;AAEvC,MAAM,WAAW,uBAAuB;IACtC,0EAA0E;IAC1E,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACzC,2FAA2F;IAC3F,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACzC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,GAAG,SAAS,CAAC;IAC7C,sCAAsC;IACtC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1C;;;;;;OAMG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,gBAAgB,CAAC,aAAa,CAAC,GAAG,SAAS,CAAC;IACnE,+EAA+E;IAC/E,QAAQ,CAAC,QAAQ,CAAC,EAAE,gBAAgB,CAAC,UAAU,CAAC,GAAG,SAAS,CAAC;CAC9D;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,GAAE,uBAA4B,GAAG,gBAAgB,CAwC9F;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,kBAAkB,GAAG,mBAAmB,CA2EzF;AAmJD,6EAA6E;AAC7E,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED,gFAAgF;AAChF,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAE/F;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,GAAE;IACjD,6DAA6D;IAC7D,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACxC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACzC;;;;;;OAMG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACxC,GAAG,WAAW,CAAC,gBAAgB,CAAC,aAAa,CAAC,CAAC,CA4CpD"}