diff --git a/docs/review/device-qa/README.md b/docs/review/device-qa/README.md index 3d3998f3..9afb0198 100644 --- a/docs/review/device-qa/README.md +++ b/docs/review/device-qa/README.md @@ -25,4 +25,24 @@ Spec: `2377b99c6b6d1654e2cb976ee1b7e07b75c77e1a`. No gameplay, content, arena, o No release or full-QA pass is claimed. Further animation/clipping symptoms require reproduction on the candidate; issues remain open until verified. +## Measurement notes + +Each note records one fact about bytes or draw calls already on main. None of them closes a parent task. + +| Note | Fact | +|---|---| +| [solid-footprint-2026-11-01.md](solid-footprint-2026-11-01.md) | Two blocking solids: canvas, ink, and the blocking rectangle | +| [solid-footprint-twelve-2026-11-02.md](solid-footprint-twelve-2026-11-02.md) | The other twelve blocking solids, same three facts | +| [camera-frame-bounds-2026-11-02.md](camera-frame-bounds-2026-11-02.md) | Camera head frames and the five housings, at anchor (32, 88) | +| [enemy-sprite-bounds-2026-11-02.md](enemy-sprite-bounds-2026-11-02.md) | Five standard enemies, canvas 64×64, anchor (32, 56), body radii | +| [retest-checklist.md](retest-checklist.md) | Human rows, plus the device-sitting bot column | +| [decoration-placement-2026-11-02.md](decoration-placement-2026-11-02.md) | Twenty-one placed decoration canvases and their draw boxes | +| [tiled-planes-2026-11-02.md](tiled-planes-2026-11-02.md) | Six ground tiles and the two fog bands | +| [player-sprite-bounds-2026-11-03.md](player-sprite-bounds-2026-11-03.md) | Shipped player frames, canvas 64×64, anchor (32, 56), radius 18 | +| [boss-sprite-bounds-2026-11-03.md](boss-sprite-bounds-2026-11-03.md) | Shipped `algorithmicModerate` frames, canvas 96×96, anchor (48, 84), radius 30 | +| [shape-hazards-2026-11-03.md](shape-hazards-2026-11-03.md) | Projectile, mine, and telegraph shapes the renderer already draws | +| [unplaced-images-2026-11-03.md](unplaced-images-2026-11-03.md) | Motif, telegraph, and objective PNGs the draw path does not place | +| [hud-shapes-2026-11-03.md](hud-shapes-2026-11-03.md) | HUD and control PNGs, and the shapes the HUD draws instead | +| [decoration-solid-overlap-2026-11-03.md](decoration-solid-overlap-2026-11-03.md) | No placed decoration canvas shares area with a blocking rectangle | + Next session: follow [retest-checklist.md](retest-checklist.md) (D-105 allows device checks on any build). diff --git a/docs/review/device-qa/boss-sprite-bounds-2026-11-03.md b/docs/review/device-qa/boss-sprite-bounds-2026-11-03.md new file mode 100644 index 00000000..f8dfef65 --- /dev/null +++ b/docs/review/device-qa/boss-sprite-bounds-2026-11-03.md @@ -0,0 +1,21 @@ +# Boss sprites against the body radius + +Measured 2026-11-03 from the runtime asset bytes on `c700b82`. No new frame was added. This note is `algorithmicModerate` only. It does not change D-118 path search, and it does not change the boss step of 120 in `IsolatedKernel`. + +Image coordinates start at the top left of the PNG. Bounds are inclusive. A pixel counts as nontransparent when its alpha is greater than 0. + +`combat-content-009` gives this boss radius 30 and base speed 96. `WorldRenderer.spriteBox` draws the role at 96×96. Every clip of this role in `clip-metadata-001` has anchor (48, 84) in that box. `SpriteLibrary.anchorPoint` turns that into SpriteKit (0.5, 12/96). The body circle is centered on the entity, which is that anchor. + +This role has no idle clip. The states are `safetyRationale`, `narrowTailoring`, `temporaryOrder`, `independentReview`, `phaseTransition`, `stagger`, and `defeat`. The table is south frame 01 of each state. + +Every measured frame has canvas 96×96. There are 172 frames. Across every frame, nontransparent width runs 35–88 and height runs 39–88. + +| Frame | Bounds | Span | sha256 | +|---|---|---|---| +| `actor_algorithmicModerate_safetyRationale_s_01@1x.png` | x 13–90, y 0–87 | 78×88 | `832d937f36bb9f6c1ebe8ca7d4925142da6f82c5afc39aaa34b93d6a105a1ac0` | +| `actor_algorithmicModerate_narrowTailoring_s_01@1x.png` | x 11–85, y 0–87 | 75×88 | `dc9c3e0f617b0a0e7645d413eb61ca31c1a0cc1cd89df301ae38c7567d9fcac0` | +| `actor_algorithmicModerate_temporaryOrder_s_01@1x.png` | x 12–91, y 28–83 | 80×56 | `6aed0d8fdf29de26a5e70c92a5733a9e0b46f79c8a167e2556c62546c67a4ba7` | +| `actor_algorithmicModerate_independentReview_s_01@1x.png` | x 4–91, y 0–87 | 88×88 | `677fc767408cee1851a309a07e9d02ddf2aa74df0848dbdedb986ad126a8ea68` | +| `actor_algorithmicModerate_phaseTransition_s_01@1x.png` | x 19–80, y 0–87 | 62×88 | `992c9c1932ef4995db7d914baaeb8ca34df45efc82612abae08dab909b56cba1` | +| `actor_algorithmicModerate_stagger_s_01@1x.png` | x 42–91, y 31–83 | 50×53 | `f51c4615bcfc7682b87fd06d281ca2921da423e39a671c18fa84ea011efe7afa` | +| `actor_algorithmicModerate_defeat_s_01@1x.png` | x 9–85, y 0–87 | 77×88 | `f06739049fe24fded4aa913afcc1b318c3cf8d7f5a68890ab0f0af6d92817744` | diff --git a/docs/review/device-qa/decoration-solid-overlap-2026-11-03.md b/docs/review/device-qa/decoration-solid-overlap-2026-11-03.md new file mode 100644 index 00000000..f12c5131 --- /dev/null +++ b/docs/review/device-qa/decoration-solid-overlap-2026-11-03.md @@ -0,0 +1,11 @@ +# Placed decorations against blocking rectangles + +Compared 2026-11-03 from the boxes already published on `c700b82`. No rectangle moved. No collision changed. This does not close T1046. + +The solid rectangles are the fourteen "rectangle runs" lines in `solid-footprint-2026-11-01.md` and `solid-footprint-twelve-2026-11-02.md`. The decoration boxes are the canvas boxes in `decoration-placement-2026-11-02.md`. Those boxes are edges: the far edge is the near edge plus the size. The two rail strips stay in their unrotated boxes. The phoenix box stays at the 153.6 draw size. + +An overlap here means the two boxes share area. Sharing only an edge is not an overlap. + +None of the 21 placed canvas boxes shares area with a blocking rectangle. + +`dec-17` and `solid-10-grid-island-b` meet at x 1856. The decoration box is x 1856–1904, y 808–952. The solid runs x 1728–1856, y 896–1024. Their y ranges meet from 896 to 952. The shared x edge has no area. diff --git a/docs/review/device-qa/hud-shapes-2026-11-03.md b/docs/review/device-qa/hud-shapes-2026-11-03.md new file mode 100644 index 00000000..1993ba1d --- /dev/null +++ b/docs/review/device-qa/hud-shapes-2026-11-03.md @@ -0,0 +1,48 @@ +# HUD images and the shapes the HUD draws + +Measured 2026-11-03 from the runtime asset bytes and `HUDRenderer` on `c700b82`. No meter was added. No icon was added. No layout changed. + +`HUDRenderer` does not sample these PNGs. It draws `SKShapeNode`s and, for some of them, sets `name` to the asset id. The authored rects below are `HUDLayout` points on the 844×390 reference. `HUDProjector` maps a rect into the safe rectangle and divides by `pointsPerSceneUnit` to get scene units. `HUDRenderer.framingScale` is `PresentationCamera.visibleWidth / 896`, which is 704/896, and it scales stroke width and font size. + +Image coordinates start at the top left of the PNG. Bounds are inclusive. A pixel counts as nontransparent when its alpha is greater than 0. Every file below is 128×128. + +## Shapes that carry an asset id + +| Asset id | Shape | Authored size | +|---|---|---| +| `hud_integrity_frame` | Rectangle frame, clear fill, stroke width `1 * framingScale` | 220×20 (`playerIntegrity`) | +| `hud_exposure_bar` | Same frame treatment | 300×24 (`exposureBar`) | +| `hud_boss_bar` | Same frame treatment | 360×24 (`bossIntegrity`) | +| `hud_extraction_ring` | Arc, clear fill, stroke width `3 * framingScale`, radius half the mapped height | 220×56 (`extractionCountdown`) | +| `hud_upgrade_signal_jammer`, `hud_upgrade_ricochet_pulse`, `hud_upgrade_ghost_step` | Rounded square, corner radius one eighth of the side. The name is the equipped upgrade's id. The PNG is not drawn | 64×64 (`upgradeBadge`) | +| `hud_camera_notch_full`, `hud_camera_notch_empty` | Rectangle. Three notches. Each is `0.6 * step` by `step`, and `step` is 14 points after mapping | Beside `cameraObjective` (180×28) | +| `control_stick_base` | Circle. Radius is half the mapped stick width | Stick rect 144×144, so the authored radius is 72 | +| `control_stick_knob` | Circle. Radius is 0.42 of the base radius | | +| `control_dodge` | Circle. Radius is half the mapped dodge width | 88×88 | +| `control_pause` | Rounded rectangle, corner radius 4 | 44×44 | + +`RuntimeAssetRegistry.HUD.cameraCounter` and `HUD.detection(_:)` have no draw call. The detection label on screen is text. + +## PNG canvases + +| File | Bounds | Span | Ink | sha256 | +|---|---|---|---|---| +| `hud_integrity_frame@1x.png` | x 4–123, y 5–122 | 120×118 | 7957 | `8f7cab5822b4bbbd143d92d047013d2c89d64db9de7db659094b3f3d7030a242` | +| `hud_exposure_bar@1x.png` | x 4–123, y 24–122 | 120×99 | 5591 | `a6cdc8d30ea3583373a3081c166c619ed94974ef63af7eed3e64ceabe7adf143` | +| `hud_boss_bar@1x.png` | x 4–123, y 16–118 | 120×103 | 7133 | `4e36da2a82fcc214aabc137c31f2b3abcae8a7f1a6b6e049a45aa748d3662041` | +| `hud_extraction_ring@1x.png` | x 4–123, y 4–121 | 120×118 | 6586 | `7c24780464eea7dfb5960fd6e170392669268dd959b6a4cd6072be1172507085` | +| `hud_upgrade_signal_jammer@1x.png` | x 4–123, y 4–123 | 120×120 | 10467 | `ccc4f235dff1defe1aa07f14934b887994263d5efd2761c85821291d9403b092` | +| `hud_upgrade_ricochet_pulse@1x.png` | x 4–123, y 4–122 | 120×119 | 9347 | `621a4c4b81c9d51abff9098be3fed388d49fb4becb3a7722f9c5d2e0e484d0b3` | +| `hud_upgrade_ghost_step@1x.png` | x 4–123, y 4–123 | 120×120 | 11033 | `c2162d65a726a00478472ea1113d88ec1f47d46aa645776e4e348ac713ce240a` | +| `hud_camera_notch_full@1x.png` | x 4–123, y 9–117 | 120×109 | 7878 | `28a5ffe0a1b53c87cbd30be782194a0f422f88a85b638a7a176d65edfb0dc151` | +| `hud_camera_notch_empty@1x.png` | x 5–123, y 15–112 | 119×98 | 6807 | `8d6f390de279a11d51230ea17d549dee28f13f9e785843474570cfd8f895ecfd` | +| `hud_camera_counter@1x.png` | x 4–123, y 14–112 | 120×99 | 6981 | `8b4c128c5baa40b7d643c4eef9f2a575edbaa960a91e887300812aa91648db77` | +| `hud_detection_hidden@1x.png` | x 4–123, y 5–122 | 120×118 | 8788 | `03cc259eec0c58240a9e00374ee3d03a52a97dc44affb8cb90b1e2367e06996b` | +| `hud_detection_observed@1x.png` | x 4–123, y 4–123 | 120×120 | 8394 | `9fd9fe10f1f8f9ab928589b2748d4f223ca68f7ab691433fc89df8e6dd7c51ce` | +| `hud_detection_tracked@1x.png` | x 4–123, y 4–122 | 120×119 | 9969 | `b7177f0e6e7b292105710bab9200dea5299e9e3155b41c9148498b537d1a207d` | +| `hud_detection_hunted@1x.png` | x 4–123, y 4–123 | 120×120 | 11162 | `8c4fa7435438ea622f6ad645b4643035a8257544396e6392053e873d5950087d` | +| `hud_detection_lockdown@1x.png` | x 4–123, y 4–123 | 120×120 | 10391 | `4ccf2ab8835a2402a31be4e09022135fcda903e27a541548e878dd0d5a1281c1` | +| `control_stick_base@1x.png` | x 4–123, y 4–123 | 120×120 | 10318 | `6da636a79334ec0a03471d5b9797c19a1f3677d97c4a1e21d291acb98dbe6cd6` | +| `control_stick_knob@1x.png` | x 4–123, y 6–121 | 120×116 | 8807 | `8ac52562bbb93443573648a8e519e0b088822b6a9ba0c8530e3e34236ee9a3b6` | +| `control_dodge@1x.png` | x 4–123, y 4–123 | 120×120 | 9176 | `2787cabab60f899a21c43c2877e14a78de4d382852d1aa4945f47ab173dfadbe` | +| `control_pause@1x.png` | x 4–123, y 4–123 | 120×120 | 9971 | `a80ca918ede6b63bc844394c57400b1f766b76833f96172603842143617f0de8` | diff --git a/docs/review/device-qa/player-sprite-bounds-2026-11-03.md b/docs/review/device-qa/player-sprite-bounds-2026-11-03.md new file mode 100644 index 00000000..026bcf56 --- /dev/null +++ b/docs/review/device-qa/player-sprite-bounds-2026-11-03.md @@ -0,0 +1,31 @@ +# Player sprites against the body radius + +Measured 2026-11-03 from the runtime asset bytes on `c700b82`. No new frame was added. No facing was authored. This does not close #131 or #132, and it does not prove a live cycle. + +Image coordinates start at the top left of the PNG. Bounds are inclusive. A pixel counts as nontransparent when its alpha is greater than 0. + +`PlayerBody.radiusUnits` is 18. `WorldRenderer.spriteBox` draws the player at 64×64. Every player clip in `clip-metadata-001` has anchor (32, 56) in that box. `SpriteLibrary.anchorPoint` turns that into SpriteKit (0.5, 8/64). The body circle is centered on the entity, which is that anchor. One image pixel is one world unit on this 64×64 canvas. + +Every measured player frame has canvas 64×64. There are 144 frames. Across every frame, nontransparent width runs 10–56 and height runs 17–64. + +The south idle cycle is the four `idle_s` frames of `player_idle`. The south move cycle is the six `move_s` frames of `player_move`. + +## South idle + +| Frame | Bounds | Span | sha256 | +|---|---|---|---| +| `actor_player_idle_s_01@1x.png` | x 20–42, y 5–55 | 23×51 | `f45ca16776f7e4b4475ef8f7cbe7791abbb4b371f24902b600c5d8468a8dd6f4` | +| `actor_player_idle_s_02@1x.png` | x 19–44, y 5–55 | 26×51 | `c33085f91166079e3e4fd4df74cb8cd092d7df72520ad14f5a134073db2a198d` | +| `actor_player_idle_s_03@1x.png` | x 8–58, y 10–49 | 51×40 | `f05b82d075f9a24c1963ce18a85e1c58bcaacfc022a3d6b08e9f1d7a591c181d` | +| `actor_player_idle_s_04@1x.png` | x 9–55, y 4–43 | 47×40 | `e1cff6eb05f2a1ee7ff5ace01845cdb3c193022313ecfc83d4a2d395e949ceae` | + +## South move + +| Frame | Bounds | Span | sha256 | +|---|---|---|---| +| `actor_player_move_s_01@1x.png` | x 22–42, y 7–55 | 21×49 | `7b3434af45c8bea2a987866f7041ae0299a65899f54e7c17d5012642f37d0108` | +| `actor_player_move_s_02@1x.png` | x 21–42, y 7–55 | 22×49 | `6257de74f3c8ab9fc5430ace985a3bf665b65aef5ba94901c8ce780791b03f30` | +| `actor_player_move_s_03@1x.png` | x 22–41, y 8–55 | 20×48 | `8e511f29a5958398187407d6a737582c37b63e553312076600ae0129eabb7c91` | +| `actor_player_move_s_04@1x.png` | x 21–42, y 7–55 | 22×49 | `0f11180150cb50ff04bb98a5cf56f2bd32eab4ea96cf21c6d463fc6ecd65fd1f` | +| `actor_player_move_s_05@1x.png` | x 21–42, y 7–55 | 22×49 | `afefdcd696e92623b6359e3f6347476a3282116ba8f803cdb06b28472444c45e` | +| `actor_player_move_s_06@1x.png` | x 22–41, y 8–55 | 20×48 | `cda6a276f78ba1e330b95e3995ca5efc72df940e45475ad9c51b14de2978e67e` | diff --git a/docs/review/device-qa/shape-hazards-2026-11-03.md b/docs/review/device-qa/shape-hazards-2026-11-03.md new file mode 100644 index 00000000..e48c2409 --- /dev/null +++ b/docs/review/device-qa/shape-hazards-2026-11-03.md @@ -0,0 +1,19 @@ +# Shape hazards the renderer already draws + +Read 2026-11-03 from `WorldRenderer` on `c700b82`. No color, width, or fill was changed. Runtime `#167` stays unmerged. The D-121 widths of 2 and 4 are not adopted. T1060 stays open because the mine fill is not clear. + +## Projectiles + +`renderProjectiles` builds an `SKShapeNode` circle whose radius is the projectile's radius. The stroke is clear. The fill is `Palette.playerProjectile` `SKColor(red: 1, green: 0.94, blue: 0.78, alpha: 1)` or `Palette.hostileProjectile` `SKColor(red: 0.95, green: 0.45, blue: 0.30, alpha: 1)`. + +The trail is a line from the previous position to the current position. Its line width is the same radius. The trail colors are the same RGB at alpha 0.35 for the player and 0.30 for a hostile shot. + +The player shot radius set in `Targeting.projectileRadius` is 4. The Witch shot radius in `combat-content-009` is 6. `narrowTailoring` and `independentReview` use radius 7. `safetyRationale` and `temporaryOrder` are not these filled circles. + +## Mines + +`renderMines` builds a filled circle of the mine's radius. The Vendor mine radius in `combat-content-009` is 42. The fill is `Palette.mineArmed` `SKColor(red: 0.85, green: 0.35, blue: 0.25, alpha: 0.35)` when armed, and `Palette.mineArming` `SKColor(white: 0.6, alpha: 0.15)` while arming. The stroke is `Palette.mineStroke` `SKColor(red: 0.9, green: 0.5, blue: 0.35, alpha: 0.8)`. The line width is 3 when armed and 1 while arming. + +## Telegraphs + +`renderTelegraphs` draws a cone, a lane, or an emitter field from the snapshot. It does not sample a telegraph PNG. The stroke is `Palette.telegraphStroke` `SKColor(red: 0.95, green: 0.55, blue: 0.35, alpha: 0.9)`. The line width is 4 when locked and 2 otherwise. `Palette.telegraphFill` uses alpha 0.42 when locked, and `0.10 + 0.22 * progress` otherwise. diff --git a/docs/review/device-qa/unplaced-images-2026-11-03.md b/docs/review/device-qa/unplaced-images-2026-11-03.md new file mode 100644 index 00000000..1f4d6665 --- /dev/null +++ b/docs/review/device-qa/unplaced-images-2026-11-03.md @@ -0,0 +1,44 @@ +# Images the civic-seam draw path does not place + +Measured 2026-11-03 from the runtime asset bytes on `c700b82`. No image was placed, deleted, or made runtime-eligible. + +Image coordinates start at the top left of the PNG. Bounds are inclusive. A pixel counts as nontransparent when its alpha is greater than 0. + +## Motifs the arena does not place + +Phoenix is the motif `civic-seam-arena-004` places. These three are in the bundle. `EnvironmentLibraryTests` lists them, and `projectionPlane` for `env_motif_repair` is unresolved. No renderer samples the files. + +| File | Canvas | Bounds | Span | sha256 | +|---|---|---|---|---| +| `env_motif_repair@1x.png` | 1024×1024 | x 32–991, y 197–825 | 960×629 | `3ea59425896705822aaab310234e462ae9d228174fbd3ef54988fd0f472489f1` | +| `env_motif_counter_signal@1x.png` | 1024×1024 | x 65–958, y 32–991 | 894×960 | `dd0756a98a26f5ca654354b6efca982e9a9f6eb75789c5b7b500c02aecf40052` | +| `env_motif_broadcast_glyph@1x.png` | 1024×1024 | x 189–834, y 32–991 | 646×960 | `3603244843e9f6b61d1e37c792d753f24f8498c55f2dcde7ca6fc48f5fb2fda8` | + +## Telegraph PNGs + +`RuntimeAssetRegistry.Telegraph` requires these six files. No `App` renderer reads that enum. `renderTelegraphs` draws shapes, as recorded in the shape-hazard note. The asset catalog already says the daemon telegraph files are evidence only. + +| File | Canvas | Bounds | Span | sha256 | +|---|---|---|---|---| +| `telegraph_daemon_query@1x.png` | 128×128 | x 4–123, y 4–123 | 120×120 | `cacf1edae74c2693cc6dbcf5d48f879a78bc2546bc244c5f53f90980271a8216` | +| `telegraph_daemon_dash@1x.png` | 128×128 | x 4–123, y 4–123 | 120×120 | `4381bf1837e95ffd1868e568a921f0203a50749b3645de7fe65ffbdf2d263f73` | +| `telegraph_safety_rationale@1x.png` | 128×128 | x 4–123, y 4–123 | 120×120 | `16f2b6db5b83243b18f910bdb272a6b54280dc485062a3ba3b6b6bbd53d114eb` | +| `telegraph_narrow_tailoring@1x.png` | 128×128 | x 4–123, y 4–123 | 120×120 | `f83e874d0303822aa72d9c8a07b68ae7f78322d5e7ffc960e119445301b70554` | +| `telegraph_temporary_order@1x.png` | 128×128 | x 4–123, y 4–123 | 120×120 | `03cdc90c6e910980719155a1cddacb7fede9278ce4334601ff5a5854bbc0eac5` | +| `telegraph_independent_review@1x.png` | 128×128 | x 4–123, y 4–123 | 120×120 | `02ba0c573105af49a9b844bb4e79a616f53d652c9b8aa19a1478b0721739e9f8` | + +## Objective PNGs + +`RuntimeAssetRegistry.Objective` requires `objective_phoenix_steps_locked`, `objective_phoenix_steps_armed`, and `objective_network_blackout`. No renderer reads that enum. The camera objective on the HUD is the text `CAM n/8` and `NETWORK BLACKOUT 8/8`. + +| File | Canvas | Bounds | Span | sha256 | +|---|---|---|---|---| +| `objective_phoenix_steps_locked@1x.png` | 128×128 | x 4–122, y 4–123 | 119×120 | `bf077c606b3b18f0a70a14541396bc48618de0e3c02c0743a63fb296870f5987` | +| `objective_phoenix_steps_armed@1x.png` | 128×128 | x 4–123, y 4–123 | 120×120 | `18a2db3912470dc60e31152f1e357244cac9aa417a6a99a6fa35d279bc1da0d2` | +| `objective_network_blackout@1x.png` | 128×128 | x 4–123, y 4–123 | 120×120 | `fc3772097b73c35fb7457d5b2533bf3147d35c89c5e01bc1fb8b73feea38992e` | + +## Elite frames, not the boss + +`improperSearchDaemon` is not `algorithmicModerate`. The bundle has 156 frames of it, and every canvas is 80×80. Every clip anchor is (40, 70). On the 80×80 `spriteBox`, that is SpriteKit (0.5, 10/80). Content radius is 26. + +`civic-seam-arena-004` already has `trigger-elite` with `encounterId` `improperSearchDaemon`, and `gate-elite-forward` owned by that id. This note does not add a spawn and does not tabulate those frames.