feat: add mobile web preview delivery

This commit is contained in:
2026-08-12 19:10:41 +08:00
parent 7e4705de0f
commit f0aa847380
16 changed files with 252 additions and 7 deletions
+3
View File
@@ -1,6 +1,9 @@
.DS_Store
tmp/
build/
!runtime/build/
runtime/build/*
!runtime/build/.gdignore
dist/
node_modules/
runtime/.godot/
+5
View File
@@ -76,6 +76,11 @@ acceptance, fun, listening and willingness to continue remain open, as do
physical device, packaging, store and release gates. No later page is
authorized by this candidate.
The Owner subsequently authorized one private remote H5 preview of this exact
candidate. That authorization is limited by
`docs/runtime/PHASE9_0_WEB_PREVIEW.md`; it does not reopen product scope or
grant device, store, publishing or release acceptance.
## Legal Terminal
`Aetherbound Guild P9.0 boot and Title candidate ready`
@@ -9,3 +9,4 @@ separate.
| 2026-08-12 | fixed source `e7eb408`; `p9-1-e7eb408-attempt01` | `P9_1_RUNTIME_CANDIDATE_READY` | Fresh isolated Git archive passes domain `cases=40`, parsed ScreenTouch `touch=25 fallback=0 direct=0`, layout `fixtures=18`, six-state normal rendering at exact `1280x720`, `844x390` and `390x844`, and existing design/economy/loadout/provenance regressions. The 28-row ignored evidence inventory SHA-256 is `7ff16f1a231e6c76dba0ec0545ea112f0afcc87f611b2ceb7ea953bbe7d22384`; strict diagnostics are clean and no owned Godot process remains. `844x390` and `390x844` captures are domain-fixture render evidence with no touch claim. Automated/runtime and agent visual gates pass; Owner understanding, choice, fun, visual/listening, device and release remain open. P9.2 stays frozen. |
| 2026-08-12 | Owner sequencing clarification after P9.1 candidate | `P9_1_PRESERVED_P9_0_ACTIVE` | Owner rejected the broad delivery rhythm, not the preserved source, and required real UI/code to proceed page by page from launch. P9.1 is not Owner-accepted. P9.0 now owns only Boot verification and the no-run Title; Start New Game may hand off to the existing Contract page. P9.1 review and P9.2 remain frozen. |
| 2026-08-12 | fixed source `f881920`; `p9-0-f881920-attempt01` | `P9_0_BOOT_TITLE_CANDIDATE_READY` | Fresh isolated Git archive passes the ordered nine-resource Boot and visible verified terminal, no-run Title, parsed ScreenTouch `touch=5 fallback=0 direct=0`, initial keyboard/controller focus, layout `fixtures=6`, six normal-render Boot/Title frames at exact `1280x720`, `844x390` and `390x844`, affected P9.1 regressions and current design/economy/loadout/provenance gates. Strict diagnostics are zero. The 27-row evidence content inventory verifies 27/27 with SHA-256 `3c34f1742357d0cc57e8c4c59124133b8fb92de0a2dec01a90b2bbcf4ffb8318`. Automated/runtime and agent visual gates pass; Owner understanding, visual acceptance, fun, listening, device and release remain open. Later pages remain frozen. |
| 2026-08-12 | Owner Web preview request | `P9_0_WEB_PREVIEW_AUTHORIZED` | Owner requested a dedicated remote H5 page for phone review. Only a non-threaded Godot Web export, browser verification and private Artifact Gallery deployment of fixed P9.0 content are authorized. Product behavior, later pages, native packages, stores and release remain frozen. |
+5 -5
View File
@@ -6,11 +6,11 @@
boot_verifying -> title_no_run -> new_game_contract
```
Boot verifies the required local scene, domain, world, actor and equipment
resources in stable order. A failed check retains the failed path and offers a
real Retry action. A successful check presents a real `9 / 9 resources ready`
terminal before entering Title. Boot itself spends nothing and creates no save
or run.
Boot verifies the required local scene, domain, world, actor, equipment and
embedded UI font resources in stable order. A failed check retains the failed
path and offers a real Retry action. A successful check presents a real
`10 / 10 resources ready` terminal before entering Title. Boot itself spends
nothing and creates no save or run.
Title exposes:
+47
View File
@@ -0,0 +1,47 @@
# Phase 9.0 Web Preview Delivery
## Owner Authorization
On 2026-08-12 the Owner requested a dedicated remote H5 page for phone review
of the accepted P9.0 runtime candidate. This authorizes only a Godot Web export,
local browser verification and private Artifact Gallery deployment.
## Content Boundary
- Product behavior authority remains P9.0 source
`f881920b1be29933169950429d4e55d8cac825d8`; the Web-compatible successor may
add only the embedded font, stream-playback selection, export configuration
and capture-harness cleanup required by this delivery.
- The Web package may expose the preserved Contract page only through the
already accepted `Start New Game` handoff.
- It may not change Boot, Title, Contract, Recruit, Market, battle, economy,
save, art, audio or content authority.
- Tests, evidence, build outputs, source documents and repository history must
not be included in the exported PCK.
## Delivery Contract
- Preset: `Web Preview` in `runtime/export_presets.cfg`.
- Template: Godot 4.6.1 non-threaded Web release, so the private remote page
does not require cross-origin isolation headers.
- Canvas: browser-window responsive, canvas focused on startup, experimental
mobile virtual keyboard enabled.
- Portrait phones show an explicit rotate-to-landscape overlay instead of a
tiny letterboxed game canvas; rotating to landscape reveals the game.
- Local output: ignored `runtime/build/web-preview/<product-source>/`.
- Remote output: the smallest self-contained export directory, published as a
dedicated Artifact Gallery HTML item.
Verify export success, expected HTML/JS/WASM/PCK files, exact ZIP data-package
contents with zero `tests/`, `evidence/` or `build/` entries, local HTTP loading,
real browser canvas dimensions, portrait rotation guidance, one canvas click
and the `Start New Game` handoff. Verify the Gallery health and signed share URL
after publication.
The browser build embeds `runtime/assets/fonts/NotoSansSC.ttf` and its
`runtime/assets/fonts/OFL.txt` license so Simplified Chinese does not depend on
a host font. `PrototypeSFX` must use Godot stream playback; a Web backend may
not select sample playback for `AudioStreamGenerator`.
This is a browser preview, not physical-device, packaging, store, publishing or
release acceptance. Owner review of the remote page remains a human gate.
Binary file not shown.
@@ -0,0 +1,36 @@
[remap]
importer="font_data_dynamic"
type="FontFile"
uid="uid://drqjmcfs0e77b"
path="res://.godot/imported/NotoSansSC.ttf-53e7d2951cb723449d16fcecb813db38.fontdata"
[deps]
source_file="res://assets/fonts/NotoSansSC.ttf"
dest_files=["res://.godot/imported/NotoSansSC.ttf-53e7d2951cb723449d16fcecb813db38.fontdata"]
[params]
Rendering=null
antialiasing=1
generate_mipmaps=false
disable_embedded_bitmaps=true
multichannel_signed_distance_field=false
msdf_pixel_range=8
msdf_size=48
allow_system_fallback=true
force_autohinter=false
modulate_color_glyphs=false
hinting=1
subpixel_positioning=4
keep_rounding_remainders=true
oversampling=0.0
Fallbacks=null
fallbacks=[]
Compress=null
compress=true
preload=[]
language_support={}
script_support={}
opentype_features={}
+92
View File
@@ -0,0 +1,92 @@
Copyright 2014, 2015 Adobe Systems Incorporated (http://www.adobe.com/).
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
https://openfontlicense.org
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply to
any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.
+14
View File
@@ -0,0 +1,14 @@
# Runtime Font
`NotoSansSC.ttf` is the unmodified Noto Sans SC regular font used by the Godot
runtime so Simplified Chinese rendering does not depend on a host system font.
- Font SHA-256: `a0af66489baf1f306732ff16da58d86c342e0b3b4b3674079ee2a9b0aee23258`.
- License file: `OFL.txt`.
- License SHA-256: `e2b6ccef8ef613a8fad6571020ad77c9143273a752001b42293a089da46940d0`.
- License: SIL Open Font License 1.1.
- Copyright notice: Copyright 2014, 2015 Adobe Systems Incorporated, as
recorded in `OFL.txt`.
The font is bundled unchanged. Do not rename, modify or replace it without
updating this record, its license and the Boot resource contract.
+1
View File
@@ -0,0 +1 @@
+35
View File
@@ -0,0 +1,35 @@
[preset.0]
name="Web Preview"
platform="Web"
runnable=true
advanced_options=false
dedicated_server=false
custom_features=""
export_filter="all_resources"
include_filter="assets/fonts/OFL.txt"
exclude_filter="tests/*,evidence/*,build/*"
export_path="build/web-preview/index.html"
patches=PackedStringArray()
encryption_include_filters=""
encryption_exclude_filters=""
seed=0
encrypt_pck=false
encrypt_directory=false
script_export_mode=2
[preset.0.options]
custom_template/debug=""
custom_template/release=""
variant/extensions_support=false
variant/thread_support=false
vram_texture_compression/for_desktop=true
vram_texture_compression/for_mobile=false
html/export_icon=true
html/custom_html_shell=""
html/head_include="<style>\n@media (orientation: portrait) {\n body::before {\n align-items: center;\n background: #081416;\n color: #f4f6f2;\n content: '请旋转手机,横屏体验裂脉远征团';\n display: flex;\n font: 600 18px/1.5 -apple-system, BlinkMacSystemFont, 'Noto Sans SC', sans-serif;\n inset: 0;\n justify-content: center;\n padding: 32px;\n position: fixed;\n text-align: center;\n z-index: 20;\n }\n #canvas { visibility: hidden; }\n}\n</style>"
html/canvas_resize_policy=2
html/focus_canvas_on_start=true
html/experimental_virtual_keyboard=true
progressive_web_app/enabled=false
+6
View File
@@ -1,6 +1,7 @@
extends Control
const RunState = preload("res://domain/run_state.gd")
const UI_FONT := preload("res://assets/fonts/NotoSansSC.ttf")
enum AppPage {
BOOT,
@@ -25,6 +26,7 @@ const BOOT_REQUIRED_PATHS: Array[String] = [
"res://assets/actors/wayrunner.png",
"res://assets/actors/kindhand.png",
"res://assets/equipment/eq_012_open_line_cord.png",
"res://assets/fonts/NotoSansSC.ttf",
"res://default_bus_layout.tres",
]
@@ -68,6 +70,9 @@ var sfx_playback: AudioStreamGeneratorPlayback
func _ready() -> void:
var runtime_theme := Theme.new()
runtime_theme.default_font = UI_FONT
theme = runtime_theme
build_shell()
render()
if auto_boot:
@@ -152,6 +157,7 @@ func build_shell() -> void:
audio_player = AudioStreamPlayer.new()
audio_player.name = "PrototypeSFX"
audio_player.bus = &"SFX"
audio_player.playback_type = AudioServer.PLAYBACK_TYPE_STREAM
audio_player.stream = generator
add_child(audio_player)
audio_player.play()
+2 -1
View File
@@ -30,6 +30,7 @@ func run_test() -> void:
game.boot_paths_override.clear()
await game.run_boot_verification()
expect(game.boot_verified, "required local content verified")
expect(game.theme != null and game.theme.default_font != null, "runtime uses an embedded UI font")
expect(game.boot_success_presented, "successful Boot presented a verified terminal before Title")
expect(game.page == game.AppPage.TITLE, "verified Boot reaches Title")
expect(find_control(game, "TitleScreen") != null, "Title screen is visible")
@@ -49,7 +50,7 @@ func run_test() -> void:
game.queue_free()
await drain_cleanup()
if failures.is_empty():
print("ABG_P9_0_BOOT_TITLE_OK checks=22 required=9 failure_retry=1 verified_terminal=1 no_run=1 focus=start contract_handoff=1 mutation=0")
print("ABG_P9_0_BOOT_TITLE_OK checks=23 required=10 embedded_font=1 failure_retry=1 verified_terminal=1 no_run=1 focus=start contract_handoff=1 mutation=0")
quit(0)
else:
for failure in failures:
+3 -1
View File
@@ -56,8 +56,10 @@ func capture_page(index: int, page_name: String, locale: String, text_scale: flo
var error := image.save_png(path)
if error != OK:
failures.append("capture %s failed with %s" % [page_name, error])
game.queue_free()
viewport.queue_free()
await process_frame
await RenderingServer.frame_post_draw
await create_timer(0.5).timeout
await drain_cleanup()
+1
View File
@@ -0,0 +1 @@
uid://dmedb6b4h0xan
+1
View File
@@ -0,0 +1 @@
uid://dgjk0wktghf4p