LearnNewsExamplesServices
Frontmatter
id15703
titleBlock-alignment fixer corrupts multiline callback arrows
stateClosed
labels
bugairegressionbuild
assigneesneo-gpt
createdAtJul 22, 2026, 1:10 PM
updatedAtJul 22, 2026, 5:33 PM
githubUrlhttps://github.com/neomjs/neo/issues/15703
authorneo-gpt
commentsCount0
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtJul 22, 2026, 5:33 PM

Block-alignment fixer corrupts multiline callback arrows

Closed Backlog/active-chunk-8 bugairegressionbuild
neo-gpt
neo-gpt commented on Jul 22, 2026, 1:10 PM

Context

While implementing #15153 / PR #15698, the default agent-preflight repair pass exposed a new corruption edge in check-block-alignment.mjs --fix. A valid multiline callback inside a comma-style declaration block was rewritten from observation => … to observation = > …; the later parse gate caught the resulting SyntaxError.

This is the same high-level failure class as #15072, but a distinct parser edge. The earlier fix excludes defaulted destructuring bindings; it does not distinguish a callback arrow from a bare declaration assignment.

The Problem

The current declaration collector accepts a bare continuation through:

DECL_BINDING + `\\s*=\\s*.+`

When a multiline callback has the same indentation as the comma-block's declarators, observation => observation.keep matches that grammar as if it were observation = (> observation.keep). splitAssignment() then splits at the arrow's = and the fixer re-emits it with assignment spacing:

// INPUT: valid JavaScript
function selectObservations(observations) {
    const
        selected = observations.filter(
        observation => observation.keep
    ),
        count = selected.length;

    return {selected, count}
}

// CURRENT --fix OUTPUT: invalid JavaScript
        observation = > observation.keep

Fresh reproduction on 2026-07-22:

  • node --check passes before the fixer.
  • node buildScripts/util/check-block-alignment.mjs --fix <repro> reports two aligned lines.
  • node --check then fails at observation = > observation.keep with SyntaxError: Unexpected token '>'.

The production witness was the opened filter in test/playwright/unit/ai/services/github-workflow/PullRequestReconciliationService.spec.mjs; #15153 avoided the corruption by separating that multiline expression from the surrounding comma block.

Memory Core prior art: session 090a68e6-1a28-4b20-a5fd-842ebac3e729 mapped the earlier template-mask corruption family. Knowledge Base and live tracker searches found #13670, #14212, and #15072, but no callback-arrow owner.

The Architectural Reality

  • buildScripts/util/check-block-alignment.mjs:210-241 owns DECL_BINDING, BARE_DECL, and splitAssignment().
  • buildScripts/util/check-block-alignment.mjs:289-362 collects comma-style declaration runs by regex and indentation.
  • buildScripts/util/check-block-alignment.mjs:372-401 reconstructs every accepted entry as left = value, so a false-positive match necessarily mutates =>.
  • test/playwright/unit/ai/buildScripts/util/check-block-alignment.spec.mjs is the established regression-test owner.
  • buildScripts/util/check-parse.mjs is a commit-time backstop, not permission for --fix to corrupt source.
  • Agent OS structure-map gate run on 2026-07-22: N/A for placement; the affected runtime is in the established buildScripts/util/check-*.mjs sibling family outside the map's ai/ ownership tree.

The Fix

Make the declaration parser distinguish an assignment operator from an arrow token before admitting or reconstructing a bare continuation. Prefer conservative non-mutation: if the line cannot be proven to be a declaration binding plus assignment, break the run and leave it byte-identical.

Add the exact same-indent multiline-callback reproducer and idempotency/parse assertions to the existing block-alignment spec. Preserve legitimate bare declarators and the default-free destructuring behavior already covered there.

Also repair the stale descriptive #15057 pointers in the existing regression test and parse-gate diagnostic: the fixer-corruption ticket is #15072; #15057 is the unrelated route-attribution seam on which that earlier bug happened to surface.

Contract Ledger

Target surface Source of authority Proposed behavior Fallback Docs Evidence
check-block-alignment --fix declaration parsing buildScripts/util/check-block-alignment.mjs Never classify => as a declaration assignment Leave an ambiguous line byte-identical and break the run Existing module/function JSDoc Exact callback-arrow regression plus node --check
agent-preflight repair pass buildScripts/util/agent-preflight.mjs Repair alignment without invalidating source Existing parse gate fails closed if another edge escapes Existing CLI help/JSDoc Focused preflight test and idempotent second run

Decision Record impact

none — bounded build-tool parser correction; no ADR contract changes.

Acceptance Criteria

  • The exact same-indent callback-arrow reproducer remains byte-identical around => after check-block-alignment --fix.
  • The fixed output passes node --check.
  • A second --fix run is idempotent.
  • Legitimate comma-block bare declarators still align.
  • Existing default-free destructuring and defaulted-destructuring safety tests remain green.
  • Existing template-literal corruption guards remain green.
  • Stale descriptive #15057 pointers in the fixer regression test and parse diagnostic are corrected to #15072.

Out of Scope

  • Replacing the regex-based formatter with a full JavaScript parser.
  • Changing Neo's comma-block alignment convention.
  • Removing the commit-time parse gate.
  • Refactoring unrelated alignment rules.

Avoided Traps

  • Relying only on check-parse: that prevents a bad commit but leaves the advertised repair command destructive.
  • Blanket-skipping multiline declarations: that would regress supported block-opening values and legitimate bare declarators.
  • Whitespace-only patching of the witness: splitting the production declaration avoids one instance but leaves the fixer unsafe for the next caller.

Related

Handoff Retrieval Hints

  • query_raw_memories: "block alignment fixer corrupts callback arrow"
  • Exact source anchor: DECL_BINDING / BARE_DECL / splitAssignment in buildScripts/util/check-block-alignment.mjs
  • Exact witness anchor: PullRequestReconciliationService.spec.mjs callback filtering pull_request.opened

Live latest-open sweep: checked latest 20 open issues immediately before creation on 2026-07-22; no equivalent found. A2A in-flight claim sweep: checked the latest 30 all-status messages within the 60-minute herd window immediately before creation; no overlapping claim found.