Release v0.49.0: reconcile V10 parser and performance train - #665
Merged
Conversation
- Add cgo_harness/attribution command that maps CPU profile samples to eight mutually exclusive components and writes markdown and JSON receipts - Capture endpoint profiles both the diagnostic lane and the shipped Parser.Parse route across four pinned canonical fixtures - Include interleaved A/A noise floor and cost-per-event joins to contextualize component shares - Implement a minimal pprof protobuf decoder to avoid widening the module dependency footprint - Publish first receipt and methodology documentation under docs/
- Add `recovery` attribution component (gate G5: classifier first) so recovery cost cannot hide in `other` - Reclassify pure no-table-action dispatch as `DiagnosticParserCoreRecovery` to separate locked-C recovery handoff from election pause - Upgrade compact T3 harness from root HasError to full structural parity (tree shape, spans, Missing, HasError, fields) - Record 98-to-20 witness gap in manifest denominator block with verification metadata - Log production/compact vs C oracle divergences without asserting, per S1 stop rule
- Add a unit test to pin the `labeled_statement` and `_property_name` declared-conflict retention rule directly against the generator. - Correct the root-cause comment in the javascript election parity test. The generator already retains the fork, but the shipped blob predates the fix. - Update the changelog to record the corrected root-cause and the new regression pin.
…uage symbols - Add ExternalScannerForLanguage to JavaScriptExternalScanner so it binds token slots positionally to the attached Language's external symbols, matching the pattern used by kotlin/python/swift/dart/rust/hcl scanners - Replace hardcoded jsSym* absolute IDs in Scan and helper functions with a per-instance symbol table resolved from the bound Language - Add jsDefaultSymTable fallback and remapValidSymbols translation for when the Language's external count or order diverges from jsExternalSymbolNames - Add regression test with a synthetic Language that asserts bound symbols resolve to the Language's own numbering, not the pinned defaults - Extend the positional binding umbrella test to pin the shipped javascript.bin's binding as a permanent guard
…age symbols - TypeScript and TSX external scanners used hardcoded symbol IDs (tsSym*, tsxSym*) in SetResultSymbol calls, which silently mistyped every external scan result when a grammargen-regenerated blob shifted the automaton's absolute symbol numbering - Implement ExternalScannerForLanguage on both scanners to bind token slots positionally by external index via bindExternalScannerSymbolNames, matching the pattern already used by JavaScript, Kotlin, Python, Swift, Dart, Rust, and HCL scanners - Add default symbol tables and external symbol name lists so Scan resolves results through the bound table instead of pinned constants - Add regression tests that verify positional binding with synthetic languages whose symbol IDs differ from the pinned defaults - Extend the positional binding table test to pin the currently-shipped TypeScript and TSX bindings as permanent regression guards
…nd fast path - Add dispatchSupported field to ActionRowDescriptor so the generic scheduler dispatch loop can skip the per-pass unsupported-cell check and its token-struct copy for Shift, Reduce, and Conflict rows, which are provably supported from the row kind alone - Extract condenseDirectAppend fast path in condenseWithOutcomeAtomic for the case where no incumbent boundary exists, avoiding the ~200-line fold-comparison block when only one candidate link is present
- Add runbook for v10 full-fleet performance measurement on GCP - Document VM provisioning, corpus authentication, and bisect ladder - Add index file that points to the canonical bytecode stream specification
- Change directory to `cgo_harness` before running the corpus source tool - Update the relative path for `real_corpus_sources` to match the new working directory
- Change free-space requirement from 100 GB before scan to 40 GB after materializing the corpus - Add instruction to increase boot disk size when the host has less free space
- Add `run_randomized_benchmarks.sh` to run each benchmark once per explicit shuffle seed with GOMAXPROCS=1 and -count=1 - Replace fixed-order `-count=10` runs with 20 per-seed runs for reproducible before-and-after comparisons - Require the script for all performance comparisons in AGENTS.md to prevent fixed-order bias - Document the script usage and default benchmark set in scripts/README.md
- Fuse two consecutive unary reductions into one dispatch boundary (REDUCE_CHAIN) when every predecessor edge lands in the same sole-unary-reduce row - Fuse a reduction followed by a shift into one dispatch boundary (REDUCE_SHIFT) when the reduce-then-shift landing row is static across all predecessor edges - Gate both superinstructions behind GTS_C4_REDUCE_CHAIN and GTS_C4_REDUCE_SHIFT environment variables while correctness receipts mature - Add a direct shift fast path that skips ClassifiedBoundary construction for corridor-proven shifts - Route single-header reductions through a trusted-corridor path that skips action-row revalidation and condense-candidate collection - Tighten the sparse-table binary search in corridorDispatch to use bitmask alignment instead of per-iteration multiplication
- Copy `resultErrorSummary` and `resultCompatibilityApplied` from the old tree to the reused tree to prevent loss of finalized result state - Verify preservation of these fields in `TestReuseTreeWithNewSourceKeepsPrimaryArena`
…o avoid redundant lookups - Store the subtree record in materializationPostorderFrame when pushing, so the traversal reads it from the frame instead of calling c.subtree again on pop - Clear the full frame capacity in Reset to release retained subtree record pointers
…ath counters - Inline reduceChildBuildItemForEntry into appendReduceChildrenToScratch to remove a per-child function call from the reduce hot path - Remove unused childCount, parentVisible, and lang parameters from buildReduceChildrenAllVisible and appendReduceChildrenToScratch - Pass symbol visibility as an explicit parameter to appendReduceChildItemToScratch to avoid recomputing it - Add perf counters for reduce child build paths (empty, all-visible, scratch-no-alias, scratch-general) to attribute build cost - Report new build path counters in the warm materialization benchmark
- Add --wall-timeout flag to run_parity_in_docker.sh that stops the container after a wall time limit and returns exit code 124 on expiry - Record wall timeout state, log exit code, and container exit code in metadata output - Add VM max-run-duration, Spot price cap, and timeout environment variables to the v10 GCP runbook - Add checkpoint monitoring procedure to project final duration and stop runs that exceed the wall limit
- Add a 262144-entry temporary memo tier that activates when recovery parses thrash the standard cache, retaining the standard cache for restoration after the parse completes - Share the parser bounded recovery memo with GLR merge cost comparisons and drop the unbounded fallback map when activated - Track parse operation depth so nested operations keep the temporary tier alive until the outermost operation ends - Record peak tier and collision count per tree for bounded recovery-memo observability - Shrink cNodeMemoCacheEntry from 32 to 24 bytes on amd64 by narrowing visCount to uint32 - Move uncommon recovery state into a lazy parserColdState sidecar to preserve the hot Parser layout
… replay - Add a memoization cache for syntheticRootReplayAdvanceToken keyed on (top, lookahead) to skip redundant advance computations during incremental replay - Store cached frame results in fixed-size pages (16K frames per page, 64 pages max) that bound total frame storage to 4 MiB and avoid stream-growth copies - Pack page index, offset, and output count into a single uint32 span to keep each cache entry at 4 bytes - Add 15 perf counters to track cache attempts, hits, misses, stores, cap skips, and output size distribution for profiling - Add TestSyntheticRootReplayAdvanceMemoUsesPackedStream to verify span packing round-trips and cache hits return stored frames without growing the page stream
- Add opt-in Lean 4 grammar authored with the Go DSL. The grammar targets Lean 4.32.2 and provides stable nodes for core declarations. Extension-specific syntax remains in line-scoped custom_command nodes because Lean modules extend the parser at runtime. - Add external scanner for nested block comments, documentation comments, and module documentation comments. - Add highlight captures and outline tags queries for editor integration. - Extend RegisterExtension to accept GrammarSource and TagsQuery fields. An empty GrammarSource defaults to GrammarSourceGrammargen. This lets external packages declare blob-based grammars and symbol extraction without calling Register directly. - Add corpus characterization test that validates 3,699 files from the official Lean 4.32.2 source without recovery nodes or early stops. - Keep the grammar opt-in to preserve the default 206-language graduation gates.
- Add stage M0 merge-event census that counts stack-merge events on both the reference C runtime and the production Go parser to measure the merge gap - Instrument the production merge path in glr.go behind the gts_merge_census build tag so the default build carries zero cost and an inert test ratchets that - Add a merge-event-census-cgo CI lane that builds the instrumented reference runtime from the pinned module-cache source and runs the census in Docker - Share the census corpus definition with the stage-D0 derivation-set differential so both censuses measure the same 104 constructed sources - Pin the M0 baseline (M_p/M_c = 15/191) and add the Foo[int](a) discriminator witness that spec.merge-time-election.v1 section 3 demands - Document the new gate in docs/ci-gate-coverage.md and flag the stage-D0 derivation-set census as a dark gate whose pin has already drifted from 32 to 24
- Regenerate compiled grammar binary for Lean parser
- Replace per-entry slice allocations in the close memo with fixed-size page storage, mirroring the existing advance stream paging pattern - Pack page index, offset, and output count into a 4-byte span value so the memo map stores one word per entry instead of a heap-allocated slice - Bound close frame storage to 16 MiB across 256 pages of 16384 frames each and skip memoization when capacity is full - Store zero-length closures as a zero span to avoid page allocation for empty results - Add performance counters for close output distribution, peak output size, and memo capacity skip events - Extend tests to verify packed span encoding round-trips and memo bookkeeping invariants
- Remove Language struct cloning for retry mode overrides - Restore original retry profile after the benchmark runs - Reduce allocations during benchmark initialization
- Guard replaceBest against a candidate that is already the incumbent tree - Without the guard, re-ranking releases the incumbent and clears the selected tree - Add V runtime profile that exercises the accepted-error retry ladder path
- Update CHANGELOG.md release date to 2026-08-13 and add entries for Lean 4 support, V10 fleet harness, randomized benchmark improvements, merge-event census, scanner fixes, retry corrections, bytecode corridor extensions, and replay memoization gains - Clarify in README.md that v0.49.0 is a candidate pending CI and soak, with v0.48.1 as the latest immutable release - Update bytecode-stream-spec.md to note that the stage 2 corridor compiler and VM are implemented and opt-in via GTS_C4_CORRIDOR=1 - Add BenchmarkKDLRecoveryGarbageSuffix and BenchmarkExpectedRootCanFrameLongRepeat to the randomized benchmark script default set - Update scripts/README.md to document the expanded benchmark set including recovery and replay targets
odvcencio
marked this pull request as ready for review
August 9, 2026 07:57
- Specify explicit event types for pull request triggers - Run workflows only on open, synchronize, reopen, and ready for review events - Prevent unnecessary runs on draft edits or metadata changes
- Compile definition, call, heritage, and import extraction into a 16-bit instruction stream - Reduce inspection time with a single-pass traversal - Add benchmarks and tests to verify parity with legacy extractors - Update documentation and benchmark scripts for the new extraction lanes
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Purpose
This pull request replaces the untagged staged
v0.49.0candidate. Itreconciles the active parser train with
mainand prepares the actual release.Net changeset map
The branch has 42 commits. Six leading waypoint commits are empty because their
changes already exist on
main. The effective history has 36 content commits.The net patch changes 92 files. It adds 9,792 lines and removes 714 lines. The
categories below include their tests and evidence code.
cgo_harness/,cmd/retry_profile_cert_child/,scripts/merge_event_census.go,cgo_harness/merge_event_census_test.goparsercore_c4_program.go,parsercore_c4_vm.go,internal/parsercorephase0/grammars/lean/,grammargen/lean_grammar.goparser_retry.go,parser_recover_c.go,glr.gofact_program.go,understanding.goparser_result_root_build.goCHANGELOG.md,README.md,.github/workflows/ci.ymlMeasurement and census code accounts for half of the additions. Most new lines
provide evidence, bounds, and reproducible gates.
Functional changes
Parser, recovery, and compact execution
REDUCE_CHAINandREDUCE_SHIFTC4 instructions.Fact extraction API
FactKindselection mask for definitions, calls, heritage, and imports.FactSetas the language-neutral combined result.NewFactProgramto compile grammar symbols and field identifiers once.ExtractDefinitionSpans,ExtractCalls,ExtractHeritage, andExtractImportsstable.Grammar, measurement, and release controls
The C4 corridor requires
GTS_C4_CORRIDOR=1. Each fused C4 instruction alsorequires its own gate. Default parsing does not execute those instructions.
FactProgramis opt-in. Existing extraction calls and parser behavior remainunchanged until a caller constructs and uses a program.
Performance evidence
Accepted V10 epoch
harness_out/gcp/20260808T202958Z-v10-full-5003ffba.FactProgram
The combined suite ran 20 explicit shuffle seeds. Each seed used one process,
GOMAXPROCS=1, a 750 millisecond benchmark time, and memory reporting.Definitions and calls on an existing Go tree:
p < 0.001.All four fact classes on an existing Go tree:
p < 0.001.Parse plus definitions and calls stayed neutral:
p = 0.947.Parser and replay work
The exact Swift issue #586 witness used three counterbalanced pairs against
origin/main.The current Swift profile assigns 16.17 percent flat CPU time to
cNodeMemoSlot. The witness uses the 6 MiB memo tier and records 41,881collisions. Cache locality is the next packing target.
Merge-event evidence
The stage M0 census measures 104 constructed sources.
The
Foo[int](a)witness supports election at the spanning pop. It does notsupport an unproved global shallow merge.
Correctness evidence
PR CI run
31304643870passed exact head5bbe8be1with 44 green jobs.Exact-main CI run
31305235288passed verified mergee1ce6514with 44 greenjobs. The governed soak started at
2026-08-09T09:23:07Z. It cannot completebefore
2026-08-11T09:23:07Z.Issue and pull request linkage
PR #645 remains a held draft. Its rescue-only arm creates 69 truncations while
fixing six witnesses. This release does not integrate that regression.
Mined follow-on targets
Release reconciliation
No
v0.49.0tag or GitHub release exists.v0.48.1remains the latestimmutable release.
After merge:
maincommit.main.Benchmark method
The standardized runner uses one process for each explicit shuffle seed. It
randomizes benchmark order within each process.
Revision comparisons counterbalance baseline and candidate order. FactProgram
comparisons place both equivalent arms in each shuffled combined run.
Settings:
GOMAXPROCS=1