Every app generation entrypoint creates a structured build report. Disk
builds write it to gowdk-build-report.json at the selected output root;
in-memory builds return the same file in MemoryResult.Files; failed builds
wrap the original error in buildgen.BuildError so callers can inspect the
partial report while preserving the original error text.
Callers without a real output root can use BuildMemoryWithOptions or
BuildMemoryFromIRWithOptions; an empty OutputBase uses . for deterministic
relative path metadata and does not create files or report directories.
The report is mandatory for compiler-facing build APIs. It is deterministic: it does not include timestamps or durations, so unchanged builds can still skip rewriting identical generated files.
Build timings are opt-in and separate. gowdk build --timings writes
gowdk-build-timings.json at the output root, and gowdk build --timings=<file> writes the same versioned JSON shape to a custom file. Timing
data is not printed to stdout and is not added to gowdk-build-report.json.
Schema
{
"version": 1,
"mode": "build",
"outputDir": "dist/site",
"events": [
{
"level": "info",
"stage": "validate",
"kind": "ir_valid",
"message": "compiler IR validation completed"
}
]
}
mode is build, memory, or incremental. Events use debug, info, or
error levels and record the compiler stage, a stable event kind, a message,
and optional page, route, path, and string data fields.
Current stages are:
start: compiler IR counts at build entry.validate: compiler IR and compiler contract validation.plan: SPA page, CSS, and runtime asset planning.write: page, CSS, and runtime asset writes or memory collection.manifest: route and asset manifest reads/writes.seo: optional sitemap/robots output and sitemap route exclusions.cleanup: stale changed-page output removal during incremental builds.complete: successful build summary.report: build report serialization or write failure.
Current report events include:
cache_policy: summarizes generated page, CSS, asset, and request-time cache policies.asset_obfuscation: summarizes whether production generated-asset obfuscation was enabled and how many compiler-owned browser assets were transformed.asset_obfuscated: one event per compiler-owned generated browser asset transformed byBuild.ObfuscateAssetsorgowdk build --obfuscate-assets, including before/after hashes, byte counts, and whether the payload changed.asset_size: one event per generated runtime asset, including JavaScript, source maps, WASM modules, and loaders.data.kindisjavascript,wasm,sourcemap,css, orasset;data.bytesis the generated byte count. Forassets/gowdk/islands/wasm_exec.js,data.wasmExecGoVersionrecords the Go toolchain version that supplied the runtime file.contract_reference: one event per linked or unlinkedg:command/g:queryreference, including owner, source, status, route metadata, roles, and handler/register metadata when known.realtime_subscription: one event perg:subscribereference, including query, presentation event, owner, source, status, roles, and handler/register metadata when known.query_invalidation: one event per validated domain-event to query invalidation edge used by boundg:queryregions, including query, event, owner, source, status, and guard metadata when known.sitemap_written/robots_written: emitted whenaddons/seowritessitemap.xmlandrobots.txt.seo_route_excluded: emitted whenaddons/seoexcludes a page from the build-time sitemap, withdata.reasonand rendermode. Reasons include request-time rendering, missing dynamicpaths {}, and guardless routes that the generated app denies by default.
CLI Debug Output
gowdk build --debug prints a readable version of this report to stderr while
normal generated artifact paths remain on stdout. gowdk dev forwards
--debug as a build flag, including incremental SPA rebuilds.
Example:
gowdk build --debug --out dist/site src/pages/home.page.gwdk
Generated file paths are still scriptable from stdout; report details are only
printed to stderr when --debug is present. The JSON report file is generated
for every successful disk build even without --debug.
CLI Timing Output
gowdk build --timings records elapsed phase durations and simple counters in
a separate sidecar:
{
"version": 1,
"mode": "build",
"outputDir": "dist/site",
"phases": [
{
"name": "parse_lower",
"durationMs": 1.25
}
],
"counters": {
"source_files": 1,
"files_written": 4,
"identical_writes_skipped": 0
}
}
Current phases include config_load, source_discovery, parse_lower,
ir_assembly, go_binding, ir_validation, contract_validation,
output_plan_writes, app_generation, binary_build, wasm_build,
backend_app_generation, and backend_binary_build when those paths run.
gowdk dev incremental SPA rebuilds reuse the same sidecar when --timings is
forwarded in the build flags. Incremental counters include
incremental_input_changes, incremental_page_changes,
incremental_component_changes, incremental_layout_changes,
incremental_affected_pages, files_written, and
identical_writes_skipped.
Benchmarks
Use Go's benchmark runner for repeatable compiler regression tracking:
go test ./internal/parser ./internal/gwdkanalysis ./internal/compiler ./internal/buildgen -run '^$' -bench 'Benchmark(ParseLowerPage|IRAssembly|ValidateProgram|GeneratedOutputFromValidatedIR|IncrementalRebuildChangedPage)$' -benchmem -count=5
Stable benchmark names:
BenchmarkParseLowerPage: parses and lowers one representative page source.BenchmarkIRAssembly: assembles pages/components intogwdkir.Program.BenchmarkValidateProgram: runs compiler validation on assembled IR.BenchmarkGeneratedOutputFromValidatedIR: writes SPA output from validated IR.BenchmarkIncrementalRebuildChangedPage: rewrites the changed-page incremental build path.
Capture local baselines with the command above and compare with benchstat.
CI should run benchmarks for trend data only; do not gate merges on fixed
duration thresholds because hardware and filesystem variance are expected.