Summary
The set of valid key=value attributes for lib_cli.sh options and positionals is hand-maintained in at least five separate places with no single source of truth, creating exactly the kind of divergence risk already seen (and fixed) once in this repo for Git default-branch detection (#286).
Details
For a single logical concept — "which attributes are valid on an option declaration" — lib/bash/cli/lib_cli.sh independently encodes the same list in:
__base_bash_libs_cli_attr_allowed__ — one global case statement covering name|version|description|handler|aliases|help|metavar|default|required|enum|validator|conflicts|sensitive|hidden|repeatable.
base_cli_option's explicit __base_bash_libs_cli_restrict_attrs__ 'help,metavar,default,required,enum,validator,conflicts,sensitive,hidden' call.
base_cli_positional's explicit __base_bash_libs_cli_restrict_attrs__ 'help,metavar,default,required,enum,validator,repeatable' call.
__base_bash_libs_cli_quick_validate_keys__ — a completely separate, hand-maintained case "$kind:$key" table used only by the declarative base_cli_declare front-end, repeating the same per-kind attribute sets (plus structural fields like path/name/type/tokens).
- The
for key in help metavar default required enum validator conflicts sensitive hidden; do ... done copy-out loops that appear once in base_cli_option (storing attributes) and again in base_cli_declare (translating declarative rows into imperative base_cli_option/base_cli_positional calls).
Impact
Adding, renaming, or removing an option/positional attribute requires updating all five places by hand. Missing one is silent: for example, forgetting to add a new attribute to __base_bash_libs_cli_quick_validate_keys__ would make the declarative base_cli_declare front-end reject an attribute that the imperative base_cli_option/base_cli_positional API accepts, producing two API surfaces with quietly different capabilities. This is the same class of bug as #286 (two independent implementations of the same domain fact disagreeing), just in the CLI module instead of the Git module.
Suggested fix
Derive the per-kind allowed-attribute lists from one table (e.g. a single associative array or a single function keyed by kind), and have __base_bash_libs_cli_attr_allowed__, __base_bash_libs_cli_restrict_attrs__ callers, and __base_bash_libs_cli_quick_validate_keys__ all read from it instead of hand-listing attributes independently. A focused test that walks every declared attribute and asserts base_cli_option/base_cli_positional and base_cli_declare agree on acceptance would catch future drift even before a shared table exists.
Summary
The set of valid
key=valueattributes forlib_cli.shoptions and positionals is hand-maintained in at least five separate places with no single source of truth, creating exactly the kind of divergence risk already seen (and fixed) once in this repo for Git default-branch detection (#286).Details
For a single logical concept — "which attributes are valid on an option declaration" —
lib/bash/cli/lib_cli.shindependently encodes the same list in:__base_bash_libs_cli_attr_allowed__— one global case statement coveringname|version|description|handler|aliases|help|metavar|default|required|enum|validator|conflicts|sensitive|hidden|repeatable.base_cli_option's explicit__base_bash_libs_cli_restrict_attrs__ 'help,metavar,default,required,enum,validator,conflicts,sensitive,hidden'call.base_cli_positional's explicit__base_bash_libs_cli_restrict_attrs__ 'help,metavar,default,required,enum,validator,repeatable'call.__base_bash_libs_cli_quick_validate_keys__— a completely separate, hand-maintainedcase "$kind:$key"table used only by the declarativebase_cli_declarefront-end, repeating the same per-kind attribute sets (plus structural fields likepath/name/type/tokens).for key in help metavar default required enum validator conflicts sensitive hidden; do ... donecopy-out loops that appear once inbase_cli_option(storing attributes) and again inbase_cli_declare(translating declarative rows into imperativebase_cli_option/base_cli_positionalcalls).Impact
Adding, renaming, or removing an option/positional attribute requires updating all five places by hand. Missing one is silent: for example, forgetting to add a new attribute to
__base_bash_libs_cli_quick_validate_keys__would make the declarativebase_cli_declarefront-end reject an attribute that the imperativebase_cli_option/base_cli_positionalAPI accepts, producing two API surfaces with quietly different capabilities. This is the same class of bug as #286 (two independent implementations of the same domain fact disagreeing), just in the CLI module instead of the Git module.Suggested fix
Derive the per-kind allowed-attribute lists from one table (e.g. a single associative array or a single function keyed by
kind), and have__base_bash_libs_cli_attr_allowed__,__base_bash_libs_cli_restrict_attrs__callers, and__base_bash_libs_cli_quick_validate_keys__all read from it instead of hand-listing attributes independently. A focused test that walks every declared attribute and assertsbase_cli_option/base_cli_positionalandbase_cli_declareagree on acceptance would catch future drift even before a shared table exists.