///|
pub struct GeneratedSnapshotFile {
path : String
kind : String
bytes : Int
checksum : Int
} derive(Debug, Eq)
///|
pub struct GeneratedSnapshot {
target : String
example : String
budget_profile : String
render_budget_profile : String
project_name : String
route : String
page_count : Int
file_count : Int
total_bytes : Int
max_first_screen_bytes : Int
max_update_payload_bytes : Int
max_update_operation_count : Int
route_diagnostic_route_count : Int
route_diagnostic_count : Int
unwindowed_list_child_count : Int
unkeyed_list_child_count : Int
duplicate_list_key_count : Int
communication_unresolved_review_count : Int
tool_result_missing_ack_count : Int
agent_duplicate_stream_chunk_count : Int
snapshot_full_replace_count : Int
scene_asset_count : Int
scene_remote_asset_count : Int
scene_thread_orphan_link_count : Int
scene_camera_clamped_count : Int
scene_surface_fallback_count : Int
scene_quality_issue_count : Int
degraded_scene_count : Int
top_route : String
route_risk_score : Int
profile_gate_diagnostic_count : Int
inspection_gate_diagnostic_count : Int
diagnostic_count : Int
files : Array[GeneratedSnapshotFile]
summary : String
content : String
} derive(Debug, Eq)
///|
pub fn snapshot_wechat_project(
target~ : String,
example~ : String,
project : @wechat.WechatProject,
profile : BuildProfile,
) -> GeneratedSnapshot {
snapshot_wechat_project_with_report(
target~,
example~,
project,
project.report,
profile,
budget_profile="default",
render_budget_profile="default",
)
}
///|
pub fn snapshot_wechat_project_with_report(
target~ : String,
example~ : String,
project : @wechat.WechatProject,
report : @wechat.WechatBuildReport,
profile : BuildProfile,
budget_profile? : String = "default",
render_budget_profile? : String = "default",
) -> GeneratedSnapshot {
let files : Array[GeneratedSnapshotFile] = []
for item in project.files {
files.push(snapshot_file(item))
}
let route_diagnostic_route_count = project.manifest.diagnostic_route_count
let route_diagnostic_count = project.manifest.diagnostic_count
let scene_asset_count = project.manifest.scene_asset_count
let scene_remote_asset_count = project.manifest.scene_remote_asset_count
let inspection = inspect_wechat_project(target~, example~, project, report)
let profile_gate = snapshot_profile_gate(profile, budget_profile)
let inspection_gate = snapshot_inspection_gate(inspection, budget_profile)
let diagnostic_count = report.diagnostics.length() +
profile.diagnostics.length() +
profile_gate.diagnostics.length() +
inspection_gate.diagnostics.length()
let summary = "Bunnia generated snapshot: target=\{target} example=\{example} budget=\{budget_profile} render_budget=\{render_budget_profile} route=\{project.route} files=\{project.files.length()} bytes=\{project.total_bytes} risk_route=\{inspection.top_route} risk_score=\{inspection.risk_score} route_diagnostic_routes=\{route_diagnostic_route_count} route_diagnostics=\{route_diagnostic_count} unwindowed_list_children=\{profile.unwindowed_list_child_count} unkeyed_list_children=\{profile.unkeyed_list_child_count} duplicate_list_keys=\{profile.duplicate_list_key_count} communication_unresolved_reviews=\{profile.communication_unresolved_review_count} tool_result_missing_acks=\{profile.tool_result_missing_ack_count} agent_duplicate_stream_chunks=\{profile.agent_duplicate_stream_chunk_count} snapshot_full_replaces=\{profile.snapshot_full_replace_count} scene_assets=\{scene_asset_count} scene_remote_assets=\{scene_remote_asset_count} scene_thread_orphans=\{profile.scene_thread_orphan_link_count} scene_camera_clamped=\{profile.scene_camera_clamped_count} scene_surface_fallbacks=\{profile.scene_surface_fallback_count} scene_quality_issues=\{profile.scene_quality_issue_count} degraded_scenes=\{profile.degraded_scene_count} profile_gate_diagnostics=\{profile_gate.diagnostics.length()} inspection_gate_diagnostics=\{inspection_gate.diagnostics.length()} diagnostics=\{diagnostic_count}"
let content = snapshot_content(
target, example, budget_profile, render_budget_profile, project, report, profile,
inspection, profile_gate, inspection_gate, files, summary,
)
{
target,
example,
budget_profile,
render_budget_profile,
project_name: project.name,
route: project.route,
page_count: project.page_count,
file_count: project.files.length(),
total_bytes: project.total_bytes,
max_first_screen_bytes: report.max_page_first_screen_bytes,
max_update_payload_bytes: report.max_page_update_payload_bytes,
max_update_operation_count: report.max_page_update_operation_count,
route_diagnostic_route_count,
route_diagnostic_count,
unwindowed_list_child_count: profile.unwindowed_list_child_count,
unkeyed_list_child_count: profile.unkeyed_list_child_count,
duplicate_list_key_count: profile.duplicate_list_key_count,
communication_unresolved_review_count: profile.communication_unresolved_review_count,
tool_result_missing_ack_count: profile.tool_result_missing_ack_count,
agent_duplicate_stream_chunk_count: profile.agent_duplicate_stream_chunk_count,
snapshot_full_replace_count: profile.snapshot_full_replace_count,
scene_asset_count,
scene_remote_asset_count,
scene_thread_orphan_link_count: profile.scene_thread_orphan_link_count,
scene_camera_clamped_count: profile.scene_camera_clamped_count,
scene_surface_fallback_count: profile.scene_surface_fallback_count,
scene_quality_issue_count: profile.scene_quality_issue_count,
degraded_scene_count: profile.degraded_scene_count,
top_route: inspection.top_route,
route_risk_score: inspection.risk_score,
profile_gate_diagnostic_count: profile_gate.diagnostics.length(),
inspection_gate_diagnostic_count: inspection_gate.diagnostics.length(),
diagnostic_count,
files,
summary,
content,
}
}
///|
pub fn snapshot_miniapp_project(
target~ : String,
example~ : String,
project : @miniapp.MiniappProject,
inspection : MiniappInspection,
inspection_gate : MiniappInspectionGate,
release : ReleaseReadinessReport,
budget_profile? : String = "default",
render_budget_profile? : String = "default",
) -> GeneratedSnapshot {
let files : Array[GeneratedSnapshotFile] = []
for item in project.files {
files.push(miniapp_snapshot_file(item))
}
let top_route = miniapp_top_route(project.manifest.pages)
let route_risk_score = miniapp_route_risk_score(
top_route,
project.manifest.pages,
)
let diagnostic_count = project.manifest.diagnostic_count +
inspection_gate.diagnostics.length() +
release.diagnostics.length()
let summary = "Bunnia generic miniapp snapshot: target=\{target} example=\{example} budget=\{budget_profile} render_budget=\{render_budget_profile} route=\{project.route} files=\{project.files.length()} bytes=\{project.total_bytes} risk_route=\{top_route} risk_score=\{route_risk_score} route_diagnostic_routes=\{project.manifest.diagnostic_route_count} route_diagnostics=\{project.manifest.diagnostic_count} scene_assets=\{inspection.max_scene_asset_count} profile_gate_diagnostics=0 inspection_gate_diagnostics=\{inspection_gate.diagnostics.length()} release_status=\{release.status} diagnostics=\{diagnostic_count}"
let content = miniapp_snapshot_content(
target, example, budget_profile, render_budget_profile, project, inspection,
inspection_gate, release, files, top_route, route_risk_score, diagnostic_count,
summary,
)
{
target,
example,
budget_profile,
render_budget_profile,
project_name: project.name,
route: project.route,
page_count: project.manifest.page_count,
file_count: project.files.length(),
total_bytes: project.total_bytes,
max_first_screen_bytes: max_miniapp_route_file_bytes(project.manifest.pages),
max_update_payload_bytes: 0,
max_update_operation_count: 0,
route_diagnostic_route_count: project.manifest.diagnostic_route_count,
route_diagnostic_count: project.manifest.diagnostic_count,
unwindowed_list_child_count: 0,
unkeyed_list_child_count: 0,
duplicate_list_key_count: 0,
communication_unresolved_review_count: 0,
tool_result_missing_ack_count: 0,
agent_duplicate_stream_chunk_count: 0,
snapshot_full_replace_count: 0,
scene_asset_count: inspection.max_scene_asset_count,
scene_remote_asset_count: 0,
scene_thread_orphan_link_count: 0,
scene_camera_clamped_count: 0,
scene_surface_fallback_count: 0,
scene_quality_issue_count: 0,
degraded_scene_count: 0,
top_route,
route_risk_score,
profile_gate_diagnostic_count: 0,
inspection_gate_diagnostic_count: inspection_gate.diagnostics.length(),
diagnostic_count,
files,
summary,
content,
}
}
///|
fn snapshot_profile_gate(
profile : BuildProfile,
budget_profile : String,
) -> BuildProfileGate {
let budget = if is_named_budget_profile(budget_profile) {
build_profile_budget_for_profile(budget_profile)
} else {
build_profile_budget_for_profile("default")
}
gate_build_profile(profile, budget, budget_profile~)
}
///|
fn snapshot_inspection_gate(
inspection : ProjectInspection,
budget_profile : String,
) -> ProjectInspectionGate {
let budget = if is_named_budget_profile(budget_profile) {
inspection_budget_for_profile(budget_profile)
} else {
inspection_budget_for_profile("default")
}
gate_project_inspection(inspection, budget, budget_profile~)
}
///|
fn miniapp_snapshot_file(input : @miniapp.MiniappFile) -> GeneratedSnapshotFile {
{
path: input.path,
kind: file_kind(input.path),
bytes: input.content.length(),
checksum: checksum_string(input.content),
}
}
///|
fn snapshot_file(input : @wechat.WechatFile) -> GeneratedSnapshotFile {
{
path: input.path,
kind: file_kind(input.path),
bytes: input.content.length(),
checksum: checksum_string(input.content),
}
}
///|
fn miniapp_snapshot_content(
target : String,
example : String,
budget_profile : String,
render_budget_profile : String,
project : @miniapp.MiniappProject,
inspection : MiniappInspection,
inspection_gate : MiniappInspectionGate,
release : ReleaseReadinessReport,
files : Array[GeneratedSnapshotFile],
top_route : String,
route_risk_score : Int,
diagnostic_count : Int,
summary : String,
) -> String {
let out = StringBuilder()
out.write_string("bunnia-generated-snapshot-v1\n")
write_snapshot_field(out, "target", target)
write_snapshot_field(out, "example", example)
write_snapshot_field(out, "budget_profile", budget_profile)
write_snapshot_field(out, "render_budget_profile", render_budget_profile)
write_snapshot_field(out, "project", project.name)
write_snapshot_field(out, "route", project.route)
write_snapshot_field(out, "pages", project.manifest.page_count.to_string())
write_snapshot_field(out, "files", project.files.length().to_string())
write_snapshot_field(out, "total_bytes", project.total_bytes.to_string())
write_snapshot_field(
out,
"max_first_screen",
max_miniapp_route_file_bytes(project.manifest.pages).to_string(),
)
write_snapshot_field(out, "max_update_payload", "0")
write_snapshot_field(out, "max_update_ops", "0")
write_snapshot_field(out, "diagnostics", diagnostic_count.to_string())
write_snapshot_field(
out,
"route_diagnostic_routes",
project.manifest.diagnostic_route_count.to_string(),
)
write_snapshot_field(
out,
"route_diagnostics",
project.manifest.diagnostic_count.to_string(),
)
write_snapshot_field(out, "unwindowed_list_children", "0")
write_snapshot_field(out, "unkeyed_list_children", "0")
write_snapshot_field(out, "duplicate_list_keys", "0")
write_snapshot_field(out, "communication_unresolved_reviews", "0")
write_snapshot_field(out, "tool_result_missing_acks", "0")
write_snapshot_field(out, "agent_duplicate_stream_chunks", "0")
write_snapshot_field(out, "snapshot_full_replaces", "0")
write_snapshot_field(
out,
"scene_assets",
inspection.max_scene_asset_count.to_string(),
)
write_snapshot_field(out, "scene_remote_assets", "0")
write_snapshot_field(out, "scene_thread_orphans", "0")
write_snapshot_field(out, "scene_camera_clamped", "0")
write_snapshot_field(out, "scene_surface_fallbacks", "0")
write_snapshot_field(out, "scene_quality_issues", "0")
write_snapshot_field(out, "degraded_scenes", "0")
write_snapshot_field(out, "risk_route", top_route)
write_snapshot_field(out, "risk_score", route_risk_score.to_string())
write_snapshot_field(out, "profile_gate_diagnostics", "0")
write_snapshot_field(
out,
"inspection_gate_diagnostics",
inspection_gate.diagnostics.length().to_string(),
)
write_snapshot_field(out, "inspection", inspection.summary)
write_snapshot_field(out, "inspection_gate", inspection_gate.summary)
write_snapshot_field(out, "release", release.summary)
write_snapshot_field(out, "summary", summary)
write_miniapp_snapshot_routes(out, project.manifest.pages)
write_miniapp_snapshot_route_diagnostics(out, project.manifest.pages)
write_snapshot_diagnostics(
out,
"inspection_gate_diagnostics",
inspection_gate.diagnostics,
)
write_snapshot_diagnostics(out, "release_diagnostics", release.diagnostics)
out.write_string("files:\n")
for item in files {
out.write_string(
"- \{item.path} kind=\{item.kind} bytes=\{item.bytes} checksum=\{item.checksum}\n",
)
}
out.to_string()
}
///|
fn snapshot_content(
target : String,
example : String,
budget_profile : String,
render_budget_profile : String,
project : @wechat.WechatProject,
report : @wechat.WechatBuildReport,
profile : BuildProfile,
inspection : ProjectInspection,
profile_gate : BuildProfileGate,
inspection_gate : ProjectInspectionGate,
files : Array[GeneratedSnapshotFile],
summary : String,
) -> String {
let out = StringBuilder()
out.write_string("bunnia-generated-snapshot-v1\n")
write_snapshot_field(out, "target", target)
write_snapshot_field(out, "example", example)
write_snapshot_field(out, "budget_profile", budget_profile)
write_snapshot_field(out, "render_budget_profile", render_budget_profile)
write_snapshot_field(out, "project", project.name)
write_snapshot_field(out, "route", project.route)
write_snapshot_field(out, "pages", project.page_count.to_string())
write_snapshot_field(out, "files", project.files.length().to_string())
write_snapshot_field(out, "total_bytes", project.total_bytes.to_string())
write_snapshot_field(
out,
"max_first_screen",
report.max_page_first_screen_bytes.to_string(),
)
write_snapshot_field(
out,
"max_update_payload",
report.max_page_update_payload_bytes.to_string(),
)
write_snapshot_field(
out,
"max_update_ops",
report.max_page_update_operation_count.to_string(),
)
write_snapshot_field(
out,
"diagnostics",
(report.diagnostics.length() +
profile.diagnostics.length() +
profile_gate.diagnostics.length() +
inspection_gate.diagnostics.length()).to_string(),
)
write_snapshot_field(
out,
"route_diagnostic_routes",
project.manifest.diagnostic_route_count.to_string(),
)
write_snapshot_field(
out,
"route_diagnostics",
project.manifest.diagnostic_count.to_string(),
)
write_snapshot_field(
out,
"unwindowed_list_children",
profile.unwindowed_list_child_count.to_string(),
)
write_snapshot_field(
out,
"unkeyed_list_children",
profile.unkeyed_list_child_count.to_string(),
)
write_snapshot_field(
out,
"duplicate_list_keys",
profile.duplicate_list_key_count.to_string(),
)
write_snapshot_field(
out,
"communication_unresolved_reviews",
profile.communication_unresolved_review_count.to_string(),
)
write_snapshot_field(
out,
"tool_result_missing_acks",
profile.tool_result_missing_ack_count.to_string(),
)
write_snapshot_field(
out,
"agent_duplicate_stream_chunks",
profile.agent_duplicate_stream_chunk_count.to_string(),
)
write_snapshot_field(
out,
"snapshot_full_replaces",
profile.snapshot_full_replace_count.to_string(),
)
write_snapshot_field(
out,
"scene_assets",
project.manifest.scene_asset_count.to_string(),
)
write_snapshot_field(
out,
"scene_remote_assets",
project.manifest.scene_remote_asset_count.to_string(),
)
write_snapshot_field(
out,
"scene_thread_orphans",
profile.scene_thread_orphan_link_count.to_string(),
)
write_snapshot_field(
out,
"scene_camera_clamped",
profile.scene_camera_clamped_count.to_string(),
)
write_snapshot_field(
out,
"scene_surface_fallbacks",
profile.scene_surface_fallback_count.to_string(),
)
write_snapshot_field(
out,
"scene_quality_issues",
profile.scene_quality_issue_count.to_string(),
)
write_snapshot_field(
out,
"degraded_scenes",
profile.degraded_scene_count.to_string(),
)
write_snapshot_field(out, "risk_route", inspection.top_route)
write_snapshot_field(out, "risk_score", inspection.risk_score.to_string())
write_snapshot_field(
out,
"profile_gate_diagnostics",
profile_gate.diagnostics.length().to_string(),
)
write_snapshot_field(
out,
"inspection_gate_diagnostics",
inspection_gate.diagnostics.length().to_string(),
)
write_snapshot_field(out, "report", report.summary)
write_snapshot_field(out, "profile", profile.summary)
write_snapshot_field(out, "profile_gate", profile_gate.summary)
write_snapshot_field(out, "inspection", inspection.summary)
write_snapshot_field(out, "inspection_gate", inspection_gate.summary)
write_snapshot_field(out, "summary", summary)
write_snapshot_route_inspections(out, inspection.routes)
write_snapshot_scene_assets(out, project.manifest.scene_assets)
write_snapshot_route_diagnostics(out, project.manifest.pages)
write_snapshot_diagnostics(out, "report_diagnostics", report.diagnostics)
write_snapshot_diagnostics(out, "profile_diagnostics", profile.diagnostics)
write_snapshot_diagnostics(
out,
"profile_gate_diagnostics",
profile_gate.diagnostics,
)
write_snapshot_diagnostics(
out,
"inspection_gate_diagnostics",
inspection_gate.diagnostics,
)
out.write_string("files:\n")
for item in files {
out.write_string(
"- \{item.path} kind=\{item.kind} bytes=\{item.bytes} checksum=\{item.checksum}\n",
)
}
out.to_string()
}
///|
fn write_miniapp_snapshot_routes(
out : StringBuilder,
pages : Array[@miniapp.MiniappManifestPage],
) -> Unit {
out.write_string("route_inspections:\n")
for page in pages {
out.write_string(
"- \{page.route} status=\{page.status} risk_score=\{miniapp_page_risk_score(page)} diagnostics=\{page.diagnostic_count} first_screen=\{page.file_bytes} update_payload=0 update_ops=0 nodes=\{page.node_count} events=\{page.event_count} windowed_lists=\{page.windowed_list_count} list_items=\{page.list_visible_count}/\{page.list_total_count} scene_markers=\{page.scene_visible_marker_count}/\{page.scene_marker_count} scene_regions=\{page.scene_visible_region_count}/\{page.scene_region_count} scene_assets=\{page.scene_asset_count}\n",
)
}
}
///|
fn write_snapshot_route_inspections(
out : StringBuilder,
routes : Array[RouteInspection],
) -> Unit {
out.write_string("route_inspections:\n")
for route in routes {
out.write_string(
"- \{route.route} status=\{route.status} risk_score=\{route.risk_score} diagnostics=\{route.diagnostics} first_screen=\{route.first_screen_bytes} update_payload=\{route.update_payload_bytes} update_ops=\{route.update_operation_count} nodes=\{route.node_count} events=\{route.event_count} unwindowed_list_children=\{route.unwindowed_list_child_count} unkeyed_list_children=\{route.unkeyed_list_child_count} duplicate_list_keys=\{route.duplicate_list_key_count} backend_events=\{route.backend_event_count} backend_streams=\{route.backend_stream_count} backend_reviews=\{route.backend_review_count} backend_cancels=\{route.backend_cancel_count} backend_retries=\{route.backend_retry_count} scene_markers=\{route.scene_visible_marker_count}/\{route.scene_marker_count} scene_regions=\{route.scene_visible_region_count}/\{route.scene_region_count} scene_assets=\{route.scene_asset_count} scene_remote_assets=\{route.scene_remote_asset_count} scene_package_bytes=\{route.scene_package_bytes}\n",
)
}
}
///|
fn write_snapshot_scene_assets(
out : StringBuilder,
assets : Array[@wechat.WechatManifestSceneAsset],
) -> Unit {
out.write_string("scene_assets:\n")
for item in assets {
out.write_string(
"- \{item.route}:\{item.id} kind=\{item.kind} src=\{item.src} remote=\{item.remote} estimated_bytes=\{item.estimated_bytes}\n",
)
}
}
///|
fn write_miniapp_snapshot_route_diagnostics(
out : StringBuilder,
pages : Array[@miniapp.MiniappManifestPage],
) -> Unit {
out.write_string("route_diagnostics:\n")
for page in pages {
if page.diagnostics.length() > 0 {
out.write_string("- \{page.route}\n")
for item in page.diagnostics {
out.write_string(" - \{item}\n")
}
}
}
}
///|
fn write_snapshot_route_diagnostics(
out : StringBuilder,
pages : Array[@wechat.WechatManifestPage],
) -> Unit {
out.write_string("route_diagnostics:\n")
for page in pages {
if page.diagnostics.length() > 0 {
out.write_string("- \{page.route}\n")
for item in page.diagnostics {
out.write_string(" - \{item}\n")
}
}
}
}
///|
fn write_snapshot_diagnostics(
out : StringBuilder,
name : String,
items : Array[String],
) -> Unit {
out.write_string("\{name}:\n")
for item in items {
out.write_string("- \{item}\n")
}
}
///|
fn miniapp_top_route(pages : Array[@miniapp.MiniappManifestPage]) -> String {
let mut route = ""
let mut risk = -1
for page in pages {
let current = miniapp_page_risk_score(page)
if current > risk {
risk = current
route = page.route
}
}
route
}
///|
fn miniapp_route_risk_score(
route : String,
pages : Array[@miniapp.MiniappManifestPage],
) -> Int {
for page in pages {
if page.route == route {
return miniapp_page_risk_score(page)
}
}
0
}
///|
fn miniapp_page_risk_score(page : @miniapp.MiniappManifestPage) -> Int {
page.file_bytes +
page.node_count * 32 +
page.depth * 64 +
page.event_count * 128 +
page.scene_marker_count * 32 +
page.scene_region_count * 32 +
page.scene_asset_count * 256 +
page.diagnostic_count * 10000
}
///|
fn max_miniapp_route_file_bytes(
pages : Array[@miniapp.MiniappManifestPage],
) -> Int {
let mut max = 0
for page in pages {
if page.file_bytes > max {
max = page.file_bytes
}
}
max
}
///|
fn write_snapshot_field(
out : StringBuilder,
name : String,
value : String,
) -> Unit {
out.write_string("\{name}=\{value}\n")
}
///|
fn file_kind(path : String) -> String {
if path == "bunnia.backend.js" {
"backend-js"
} else if path.has_suffix(".axml") {
"axml"
} else if path.has_suffix(".acss") {
"acss"
} else if path.has_suffix(".ttml") {
"ttml"
} else if path.has_suffix(".ttss") {
"ttss"
} else if path.has_suffix(".wxml") {
"wxml"
} else if path.has_suffix(".wxss") {
"wxss"
} else if path.has_suffix(".data.js") {
"page-data"
} else if path.has_suffix(".js") {
"js"
} else if path.has_suffix(".json") {
"json"
} else {
"asset"
}
}
///|
fn checksum_string(value : String) -> Int {
let mut checksum = 5381
for i in 0..