You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
ods-cli is a roughly 6,500-line production entry point. The repository's decomposition roadmap calls for behavior-preserving extraction of read-only formatting before stateful commands are split. Keeping status-color mapping, JSON escaping, and separator rendering inline makes their ownership unclear and forces future command extraction to move implementation and behavior at the same time.
This PR completes the first narrow Phase 1 slice: it moves only those pure primitives into lib/cli-format.sh, sources that installed module from the existing CLI, and preserves the command syntax and byte-level output contracts. ods list --json, human list/status output, template output, and table separators remain owned by the same CLI callers.
The behavioral invariant is: extracting a pure helper must not change any public CLI output, status mapping, JSON escaping, or separator width.
What changes
add lib/cli-format.sh with the three side-effect-free formatting primitives
source the module after the CLI initializes color variables, preserving NO_COLOR behavior
remove only the corresponding inline definitions from ods-cli
update the isolated installed-CLI reconciliation fixture to deploy the required module
add BATS boundary coverage for module loading, status mapping, all JSON control escapes, and separator rendering
keep .bats files LF-normalized so Windows checkouts remain executable by Bash
record the completed slice and remaining Phase 1 ownership in docs/ODS_CLI_DECOMPOSITION.md
Overlap check
Searched open and closed PRs for ods-cli decomposition formatting, cli-format, the three helper names, and every open patch touching ods/ods-cli. There are 25 open PRs touching the large CLI, but none of their patches contains _status_color, _json_escape, or hr; the closest historical result is merged PR #1100, which standardized logging/banner style rather than these helpers.
Six open PRs (#3019-#3024) touch .gitattributes; they add or consume rules for Makefiles/workflows/scripts and do not add the *.bats contract. No open PR touches lib/cli-format.sh, the new BATS contract, the reconciliation fixture, or the decomposition roadmap. The scope is independently useful and does not replace an existing implementation.
Regression coverage
Focused validation from the repository root / ods/:
bash tests/test-ods-list-json-escaping.sh — pass; exercises the public ods list --json boundary
normalized Linux-tooling run of test-cli-formatting.bats — 4/4 pass
bash tests/test-cli-enable-compose-reconciliation.sh — pass after the isolated installed-CLI fixture was updated
The repository-downloaded BATS runner in this Windows checkout had CRLF in its own ignored clone, so the same pinned runner/support/assert trees were copied to a verified /tmp/ods-bats.* directory, mechanically LF-normalized, and used for the 4/4 receipt. CI's fresh Linux checkout remains the authoritative literal tests/run-bats.sh execution.
A broad tests/contracts/test-installer-contracts.sh probe also reached an existing failure at Hermes template bounds each model turn. Neither that test nor extensions/services/hermes/cli-config.yaml.template is changed by this branch; the focused CLI and formatting contracts above pass.
Design and rollback
The module intentionally has no set -euo pipefail: it is sourced into the CLI and inherits caller policy. It expects the already-initialized color variables and performs no I/O other than returning formatted bytes. Service aliases and config masking remain in their current owners until a later independently testable slice.
Rollback is a single revert: restore the three inline functions and remove the source line/module. No persisted state, command syntax, or runtime migration is involved.
CI follow-up
The first integration-smoke run failed because test-cli-enable-compose-reconciliation.sh intentionally builds an isolated installed footprint but copied only ods-cli plus two older library dependencies. Commit bff5cbfc adds the new required module to that fixture; the exact previously failing test now passes for stale, empty, missing, and dual-marker compose states. All other test fixtures that execute a copied CLI already copy lib/*.sh or the full lib/ tree. The batch integration branch includes the fix at 2c82aaec. The rerun is fully green: 28 successful checks, 4 intentional skips, including the 3m58s integration-smoke job that originally exposed the missing fixture dependency.
Built the inspectable synthetic branch tang-vu:validation/batch-20260824-architecture from upstream main (6ff9b4fc) and merged exact candidate heads in this order:
No manual merge resolution was required, including the shared Extensions.jsx / Extensions.test.jsx surface in #3065 and #2903. Synthetic head: 2c82aaec.
Combined validation:
Dashboard: 28 files / 262 tests passed; ESLint passed; production Vite build passed
Dashboard API: 350 passed, 5 skipped across service events, main routing, extension plans, lifecycle, and dependency suites
CLI: JSON public boundary, Phase C smoke, Bash syntax, ShellCheck, 4/4 BATS formatting contract, and enable/reconciliation fixture passed
The stale Browserslist notice and authentication-dependent Phase C skips are unchanged environmental disclosures. #2903 remains draft because synthetic compatibility does not replace its declared live host-agent lifecycle gate and independent human review.
CI follow-up complete: head bff5cbfc passed the full rerun, including integration-smoke (3m58s). The initial missing-module fixture failure is resolved; no failing or pending checks remain.
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
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.
Why this matters
ods-cliis a roughly 6,500-line production entry point. The repository's decomposition roadmap calls for behavior-preserving extraction of read-only formatting before stateful commands are split. Keeping status-color mapping, JSON escaping, and separator rendering inline makes their ownership unclear and forces future command extraction to move implementation and behavior at the same time.This PR completes the first narrow Phase 1 slice: it moves only those pure primitives into
lib/cli-format.sh, sources that installed module from the existing CLI, and preserves the command syntax and byte-level output contracts.ods list --json, human list/status output, template output, and table separators remain owned by the same CLI callers.The behavioral invariant is: extracting a pure helper must not change any public CLI output, status mapping, JSON escaping, or separator width.
What changes
lib/cli-format.shwith the three side-effect-free formatting primitivesNO_COLORbehaviorods-cli.batsfiles LF-normalized so Windows checkouts remain executable by Bashdocs/ODS_CLI_DECOMPOSITION.mdOverlap check
Searched open and closed PRs for
ods-cli decomposition formatting,cli-format, the three helper names, and every open patch touchingods/ods-cli. There are 25 open PRs touching the large CLI, but none of their patches contains_status_color,_json_escape, orhr; the closest historical result is merged PR #1100, which standardized logging/banner style rather than these helpers.Six open PRs (#3019-#3024) touch
.gitattributes; they add or consume rules for Makefiles/workflows/scripts and do not add the*.batscontract. No open PR toucheslib/cli-format.sh, the new BATS contract, the reconciliation fixture, or the decomposition roadmap. The scope is independently useful and does not replace an existing implementation.Regression coverage
Focused validation from the repository root /
ods/:bash tests/test-ods-list-json-escaping.sh— pass; exercises the publicods list --jsonboundarytest-cli-formatting.bats— 4/4 passbash tests/test-phase-c-p1.sh— 7 passed, 0 failed, 9 authentication-dependent warningsbash -n ods-cli lib/cli-format.sh— passshellcheck --rcfile=/dev/null --severity=error ods-cli lib/cli-format.sh— passgit diff --check— passbash tests/test-cli-enable-compose-reconciliation.sh— pass after the isolated installed-CLI fixture was updatedThe repository-downloaded BATS runner in this Windows checkout had CRLF in its own ignored clone, so the same pinned runner/support/assert trees were copied to a verified
/tmp/ods-bats.*directory, mechanically LF-normalized, and used for the 4/4 receipt. CI's fresh Linux checkout remains the authoritative literaltests/run-bats.shexecution.A broad
tests/contracts/test-installer-contracts.shprobe also reached an existing failure atHermes template bounds each model turn. Neither that test norextensions/services/hermes/cli-config.yaml.templateis changed by this branch; the focused CLI and formatting contracts above pass.Design and rollback
The module intentionally has no
set -euo pipefail: it is sourced into the CLI and inherits caller policy. It expects the already-initialized color variables and performs no I/O other than returning formatted bytes. Service aliases and config masking remain in their current owners until a later independently testable slice.Rollback is a single revert: restore the three inline functions and remove the source line/module. No persisted state, command syntax, or runtime migration is involved.
CI follow-up
The first integration-smoke run failed because
test-cli-enable-compose-reconciliation.shintentionally builds an isolated installed footprint but copied onlyods-cliplus two older library dependencies. Commitbff5cbfcadds the new required module to that fixture; the exact previously failing test now passes for stale, empty, missing, and dual-marker compose states. All other test fixtures that execute a copied CLI already copylib/*.shor the fulllib/tree. The batch integration branch includes the fix at2c82aaec. The rerun is fully green: 28 successful checks, 4 intentional skips, including the 3m58sintegration-smokejob that originally exposed the missing fixture dependency.