Repository navigation
refactor(explorer): simplify authoringv2 command application into cohesive mutation families (#192) - #210
Draft
matthewpeterkort wants to merge 1 commit into
Conversation
… of applyCommand Extract the 29 substantial command-case bodies from the ~694-line applyCommand switch into private helpers in four family files (command_tables.go, command_routes.go, command_columns.go, command_proposals.go), grouped by table/population, route, column, and server-resolved proposal responsibility. Keep ApplyCommands as the single atomic batch pipeline, the pre-switch rowValuePolicy refusal, the small explicit command.Type switch, exact case order, and the existing tiny delegations (frame sources, ADD_COLUMN_SOURCE, ADD_SEMANTICAL via applySemanticSelections) inline. Helpers receive only their actual data dependencies; no registry, no forwarding layers, no new wire surface. Extraction was performed and verified by a rerunnable AST-based transformer that moves case bodies verbatim and token-verifies each moved body against the original apart from the deliberate per-helper result prologue; the tool also verifies case order, the unchanged ApplyCommands pipeline, and the unchanged guard prelude. Behavior evidence (identical before/after on 80e8877 base): - go test -json ./internal/explorer/authoringv2 -run TestApplyCommands -count=1: 23/23 pass, 0 skip - full authoringv2 suite: 357/357 pass, 0 skip - go test -json ./internal/explorer ./internal/explorer/lifecycle -count=1: 124/124 and 713/715 pass with the same 2 environment skips as baseline (TestBuilderFullUIRequestReplay, TestConstructionProposalOperationHistoryTraces) - 71-scenario differential dump (31 success paths, 40 refusal paths across every command family, including invalid-last mixed batches): canonical workspace digests, CommandResult JSON, and error strings byte-identical before/after; caller-input non-mutation asserted per scenario - scripts/check_no_code_comments.py on all five touched files: 0 violations Closes #192
matthewpeterkort
left a comment
Collaborator
Author
There was a problem hiding this comment.
Review of 9bd971d against base 80e8877: APPROVE - no changes required.
I re-verified the extraction independently rather than trusting the transformer receipt:
- All 29 extracted case bodies compared line-by-line against the base applyCommand: every body is verbatim; the only addition is the mechanical per-helper result prologue, identical to the original prelude, so all result-based returns are unchanged.
- ApplyCommands (clone once -> migrations -> ordered application -> normalize once -> contributor/BuilderState validation), the pre-switch rowValuePolicy refusal, the unsupported-type fallthrough, and the three inline cases (frame-source trio, ADD_COLUMN_SOURCE, ADD_SEMANTIC_SELECTIONS) are byte-identical; the dispatch switch preserves the exact case set and order.
- Control-flow audit: no fallthrough or goto; every break and continue in the moved code sits inside a for loop, so extraction cannot rebind them; the by-value mutation of command in the construction-choice path and the workspace pointer writes in root-rebase and restore preserve base semantics.
- Parameter plumbing is exact: commandID and index appear only in helpers that consume commandGeneratedID / stagedSourceColumnID / ensureConstructionRoute / applyColumnSource, and catalog only where referenced.
- Import hygiene: commands.go loses only the sort import (its sole consumer REORDER_TABLES moved out); each family file imports exactly what it uses; the 29 new helper names have no collisions and the delegation targets (applyColumnSource, applySemanticSelections, applyFrameSourceCommand, stagedSourceColumnID, ensureConstructionRoute) are untouched.
- No test files were touched; existing package coverage (357 tests) plus the documented 71-scenario canonical-bytes differential are appropriate evidence for a pure move.
Optional, non-blocking: the 29-fold result prologue is inert in helpers that never mutate it (e.g. applyCreateTableCommand), and the moved copy := shadow in applyDuplicateTableCommand and documentIndex := documentIndex(...) shadow in applyUpdateConstructionOutputCommand are carried verbatim from the base rather than introduced here. Neither needs action.
Verdict: approved.
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.
Summary
Extracts the 29 substantial command-case bodies from the ~694-line
applyCommandswitch ininternal/explorer/authoringv2/commands.gointo private helpers in four family files, grouped by the responsibilities named in #192:command_tables.go— table/population mutations (create, duplicate, delete, rename, reorder, set root, set/clear population)command_routes.go— route mutations (add, update edge, set match mode, remove)command_columns.go— column mutations (add, update, construction-output presentation, transformation, contributor set/clear, source update, row-value policy, remove)command_proposals.go— server-resolved proposal applications (root rebase incl. replace mode, construction choice, interpretation candidate, row-definition/table-shape/population-member/construction proposals, draft restore)ApplyCommandsremains the single atomic batch pipeline (clone once → migrations → ordered application → normalize once → contributor/BuilderState validation).applyCommandkeeps the shared pre-switchrowValuePolicyrefusal, the small explicitcommand.Typeswitch in unchanged case order, the unsupported-type fallthrough, and the existing tiny delegations inline (applyFrameSourceCommand,applyColumnSource,applySemanticSelections). Each helper receives only its actual data dependencies (workspace,catalog,commandID,index,commandas needed) — no service objects, no registry, no one-line forwarding layers, no new wire schema, command type, global, or backend I/O. No map iteration is used for dispatch.Closes #192.
Why this reduces reasoning burden (not line count)
ROOT_REBASE_REQUIRED, route max-hops/repeated-edge refusals, stable source-column IDs, row-value-policy bindings, server-resolution refusals) now reads as contiguous family code instead of interleaved cases, while the shared invariants (batch atomicity, ordering, clone semantics) have exactly one owner (ApplyCommands).catalog/commandID/indexappear only where the body uses them, so reasoning about a helper needs no mental model of mutable service state.Extraction tooling (>500 touched lines rule)
Transformation done by a rerunnable AST-based transformer (
go/ast+go/scanner) that:func applyXCommand(deps…) (CommandResult, error) { result := CommandResult{Type: CommandResultTableChanged, OutputID: command.OutputID}; <case body verbatim> },MATCH, 6,008 moved tokens total) apart from the deliberate per-helperresultprologue,ApplyCommandsis token-unchanged, and theapplyCommandprelude/guard (clone-once pipeline, rowValuePolicy refusal) is token-unchanged,All checks:
ALL CHECKS PASSED: 29 cases extracted, 3 remain inline, case order preserved.Verification
Focused checks first, then full suites, on base
80e88771309881e9d473d76dc2226ed10f204af9:git diff --checkgo test -json ./internal/explorer/authoringv2 -run TestApplyCommands -count=1go test -json ./internal/explorer/authoringv2 -count=1(full package)go test -json ./internal/explorer ./internal/explorer/lifecycle -count=1TestBuilderFullUIRequestReplay,TestConstructionProposalOperationHistoryTraces)go build ./...,go vet ./internal/explorer/...,gofmt -lscripts/check_no_code_comments.pyon all five touched filesPreserved named guards:
TestApplyCommandsRejectsBatchAtomically,TestApplyCommandsSourceEditsPreserveColumnIdentityAndAreIdempotent,TestApplyCommandsRejectsRouteBeyondCatalogMaxHopsWithoutMutation, and the root-rebase refusals all pass unmodified. No test expectations were changed; no test was edited.Canonical-bytes differential (before vs after trees): a 71-scenario differential harness (31 success paths + 40 refusal paths, ≥1 scenario per command family, including invalid-last mixed batches spanning multiple families, route too-long/repeated-edge refusals, root-rebase refusal, server-resolution refusals, restore semantics, replay idempotency) recorded canonical workspace digests,
CommandResultJSON, and error strings against baseline and the extracted tree: 0 differing scenarios of 71; all success-path canonical digests equal; caller-input non-mutation asserted per scenario. Behavior-preserving extraction confirmed at the observable-bytes level.Source-integrity/browser acceptance: no source-integrity map or shared-state consumer in the repo references
applyCommandinternals (verified by repo-wide search), so the ticket's conditional Builder command-browser acceptance requirement is not triggered; the two environment-skipped lifecycle tests are unchanged from baseline and are not affected by this pure-in-package move.Risks / follow-ups
resultprologue and parameter plumbing.