Skip to content

Harden the registry dispatch-table parser against benign reformatting#29

Merged
cgraf78 merged 1 commit into
mainfrom
fix-registry-dispatch-parse
Jul 2, 2026
Merged

Harden the registry dispatch-table parser against benign reformatting#29
cgraf78 merged 1 commit into
mainfrom
fix-registry-dispatch-parse

Conversation

@cgraf78

@cgraf78 cgraf78 commented Jul 2, 2026

Copy link
Copy Markdown
Owner

Summary

Make the registry validator's shell dispatch scan tolerant of cosmetic
formatting changes so a purely stylistic edit to the dispatchers can no
longer brick every format/lint/plan run.

_shell_dispatch_functions reconstructs the adapter-to-function dispatch
table by scraping the case arms of _format_dispatch/_lint_dispatch
in autoformat.sh/autolint.sh, and it runs on EVERY load_registry
(so on every checkrun format/lint/plan/explain, including the commit
hook). The old scan required the handler on the same line as the
pattern) label and detected the function end with an exact, unindented
}. A formatting-only change — moving a handler to the next line,
indenting esac, a shell formatter splitting an arm — could silently
drop arms or empty the table, which then raises RegistryError and
bricks the tool.

  • rewrite the scan to accept the handler on the same or a following
    line, tolerate blank lines between a label and its handler, and stop
    at an esac/closing brace regardless of indentation
  • preserve the loud failure on an unreadable (empty) table: the parser
    never silently returns an empty mapping that would make every selector
    look undispatched, and a wrong function value is still caught loudly by
    the existing _validate_invariants dispatch-mismatch check
  • add a prominent WHY-comment: this still derives control flow from shell
    source (a coupling the durable fix removes by making the dispatch
    mapping data the registry owns in registry.json), documents the
    reformats that are tolerated, and notes that alternation (a|b)) and
    stacked bare labels are intentionally unsupported and fail loudly
  • leave _shell_functions (an existence-set check whose miss surfaces
    loudly as "adapter is not implemented") unchanged as lower-risk

The new parser is byte-identical to the old one on the production
dispatchers (21 format arms, 27 lint arms, same keys and values).

Testing

  • new registry-test case: a reformatted-but-equivalent dispatcher
    (next-line handlers, blank lines, indented esac) parses to the exact
    expected table, and an unreadable/empty dispatcher raises
    RegistryError with the "could not be read" message
  • verified red-green: the old same-line-only parser yields an empty table
    (which raises) on the reformatted fixture
  • full suite green (./test/checkrun-test: ok); checkrun lint clean

Summary

Make the registry validator's shell dispatch scan tolerant of cosmetic
formatting changes so a purely stylistic edit to the dispatchers can no
longer brick every format/lint/plan run.

`_shell_dispatch_functions` reconstructs the adapter-to-function dispatch
table by scraping the `case` arms of `_format_dispatch`/`_lint_dispatch`
in `autoformat.sh`/`autolint.sh`, and it runs on EVERY `load_registry`
(so on every `checkrun` format/lint/plan/explain, including the commit
hook). The old scan required the handler on the same line as the
`pattern)` label and detected the function end with an exact, unindented
`}`. A formatting-only change — moving a handler to the next line,
indenting `esac`, a shell formatter splitting an arm — could silently
drop arms or empty the table, which then raises `RegistryError` and
bricks the tool.

- rewrite the scan to accept the handler on the same or a following
  line, tolerate blank lines between a label and its handler, and stop
  at an `esac`/closing brace regardless of indentation
- preserve the loud failure on an unreadable (empty) table: the parser
  never silently returns an empty mapping that would make every selector
  look undispatched, and a wrong function value is still caught loudly by
  the existing `_validate_invariants` dispatch-mismatch check
- add a prominent WHY-comment: this still derives control flow from shell
  source (a coupling the durable fix removes by making the dispatch
  mapping data the registry owns in `registry.json`), documents the
  reformats that are tolerated, and notes that alternation (`a|b)`) and
  stacked bare labels are intentionally unsupported and fail loudly
- leave `_shell_functions` (an existence-set check whose miss surfaces
  loudly as "adapter is not implemented") unchanged as lower-risk

The new parser is byte-identical to the old one on the production
dispatchers (21 format arms, 27 lint arms, same keys and values).

Testing

- new `registry-test` case: a reformatted-but-equivalent dispatcher
  (next-line handlers, blank lines, indented `esac`) parses to the exact
  expected table, and an unreadable/empty dispatcher raises
  `RegistryError` with the "could not be read" message
- verified red-green: the old same-line-only parser yields an empty table
  (which raises) on the reformatted fixture
- full suite green (`./test/checkrun-test`: ok); `checkrun lint` clean
@cgraf78 cgraf78 merged commit 45ce87f into main Jul 2, 2026
6 checks passed
@cgraf78 cgraf78 deleted the fix-registry-dispatch-parse branch July 2, 2026 01:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant