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
src/coverage.sh is 2548 lines and 59 functions — the largest file in src/, bigger
than src/runner.sh was. Apply the same module split: src/coverage/ behind a thin
aggregator.
Blocked by #923 (path-keyed embed markers). Do after #924 so the
runner split sets the convention and this one just follows it.
This is a pure move
Namespace stays bashunit::coverage::*. No renames, no call-site changes,
no behavior changes. bashunit:76 keeps its single source "$BASHUNIT_ROOT_DIR/src/coverage.sh"; that file becomes an aggregator
holding only source lines and comments.
Step 1: map the responsibilities first
Unlike #924, the target layout is not pre-decided here — nobody has mapped
this file yet. Produce the grouping before moving a single line:
every _BASHUNIT_* global: which function assigns it, which read it, and whether
anything outside src/coverage.sh touches it
proposed cohesive groups with an acyclic layering
Post that map on this issue for review, then split. Existing hints to fold in: adrs/adr-007-branch-coverage-mvp.md and adrs/adr-009-coverage-tracing-engine.md
describe the intended internal boundaries, and the 9 existing tests/unit/coverage_*_test.sh files (core, engine, branches, helpers, percent,
reporting, executable, subshell, parallel_aggregation) are a strong prior on what the
natural seams already are.
Known constraints specific to this file
.editorconfig:35 has a per-file rule, [src/coverage.sh] max_line_length = unset. Splitting leaves the new files under the global [**.sh] max_line_length = 120. The longest current line is 370 chars, so either widen the
glob to cover the directory, or reflow the offending lines. Decide deliberately and
say which in the PR — silently inheriting 120 will fail make lint.
src/coverage.sh:224 reads _BASHUNIT_RUNNER_RESULT_ORDINAL, a runner global.
That cross-module read stays as-is; do not "fix" it in this PR.
Intentional dynamic-scope mutation._branch_push_if and friends deliberately
mutate caller locals (if_decision_line, if_arms, if_depth, if_arm_start),
documented inline at src/coverage.sh:818-821 and called out in .claude/rules/bash-style.md. Those helpers and their callers must land in the same file, and the inline justification comment must travel with them.
DEBUG-trap code paths only run under --coverage, which is a nightly
non-gating workflow (.github/workflows/coverage.yml). The default suite will not
catch a regression here — run ./bashunit --coverage --parallel tests/ explicitly
before opening the PR.
make test globs one level deep only. Do not create tests/unit/coverage/.
The existing 9 flat coverage_*_test.sh files already mirror a module split — keep
that shape and rename only where a file's scope genuinely moves.
Acceptance criteria
Responsibility map posted on this issue and agreed before any code moves
git diff shows only relocations — no renamed functions, no changed logic
src/coverage.sh contains only source lines and comments
Every new file's first line is #!/usr/bin/env bash
.editorconfig line-length decision made explicitly and stated in the PR
./bashunit tests/ green
./bashunit --parallel tests/ green
./bashunit --coverage --parallel tests/ green
make sa && make lint green
bash build.sh bin -v prints ✅ Build verified ✅
Fork-budget acceptance tests green
Bash 3.0+ compatible
No CHANGELOG entry — internal, no user-visible behavior change
.claude/rules/architecture-map.md coverage row updated to the module table
Do not
Do not start moving code before the responsibility map is reviewed
Summary
src/coverage.shis 2548 lines and 59 functions — the largest file insrc/, biggerthan
src/runner.shwas. Apply the same module split:src/coverage/behind a thinaggregator.
Blocked by #923 (path-keyed embed markers). Do after #924 so the
runner split sets the convention and this one just follows it.
This is a pure move
Namespace stays
bashunit::coverage::*. No renames, no call-site changes,no behavior changes.
bashunit:76keeps its singlesource "$BASHUNIT_ROOT_DIR/src/coverage.sh"; that file becomes an aggregatorholding only
sourcelines and comments.Step 1: map the responsibilities first
Unlike #924, the target layout is not pre-decided here — nobody has mapped
this file yet. Produce the grouping before moving a single line:
bashunit::coverage::*functions call which)_BASHUNIT_*global: which function assigns it, which read it, and whetheranything outside
src/coverage.shtouches itPost that map on this issue for review, then split. Existing hints to fold in:
adrs/adr-007-branch-coverage-mvp.mdandadrs/adr-009-coverage-tracing-engine.mddescribe the intended internal boundaries, and the 9 existing
tests/unit/coverage_*_test.shfiles (core, engine, branches, helpers, percent,reporting, executable, subshell, parallel_aggregation) are a strong prior on what the
natural seams already are.
Known constraints specific to this file
.editorconfig:35has a per-file rule,[src/coverage.sh] max_line_length = unset. Splitting leaves the new files under the global[**.sh]max_line_length = 120. The longest current line is 370 chars, so either widen theglob to cover the directory, or reflow the offending lines. Decide deliberately and
say which in the PR — silently inheriting 120 will fail
make lint.src/coverage.sh:224reads_BASHUNIT_RUNNER_RESULT_ORDINAL, a runner global.That cross-module read stays as-is; do not "fix" it in this PR.
_branch_push_ifand friends deliberatelymutate caller locals (
if_decision_line,if_arms,if_depth,if_arm_start),documented inline at
src/coverage.sh:818-821and called out in.claude/rules/bash-style.md. Those helpers and their callers must land in thesame file, and the inline justification comment must travel with them.
--coverage, which is a nightlynon-gating workflow (
.github/workflows/coverage.yml). The default suite will notcatch a regression here — run
./bashunit --coverage --parallel tests/explicitlybefore opening the PR.
src/coverage.sh:173carries a comment about a name kept "from the trap-onlyera" that references
runner.sh. Update the reference if the runner path changedin refactor(runner): split src/runner.sh into a src/runner/ module #924.
Tests: keep them flat
make testglobs one level deep only. Do not createtests/unit/coverage/.The existing 9 flat
coverage_*_test.shfiles already mirror a module split — keepthat shape and rename only where a file's scope genuinely moves.
Acceptance criteria
git diffshows only relocations — no renamed functions, no changed logicsrc/coverage.shcontains onlysourcelines and comments#!/usr/bin/env bash.editorconfigline-length decision made explicitly and stated in the PR./bashunit tests/green./bashunit --parallel tests/green./bashunit --coverage --parallel tests/greenmake sa && make lintgreenbash build.sh bin -vprints✅ Build verified ✅.claude/rules/architecture-map.mdcoverage row updated to the module tableDo not
tests/unit/coverage/shfmt -w;make lintis the format gate