testsAndMisc/docs/superpowers/evidence/analyze-repo-split-2026-08-16.json
Krzysztof kuhy Rudnicki 41cc0451c9 Split analyze_repo.sh into an entry script and five libs
869 lines -> 231, with the extracted helpers and per-STEP blocks in
lib/analyze_repo_{scan,tools,separate,report,symbols}.sh (86-228 each).

The seam that mattered was STEP 4, whose two passes share a map of
language -> temp file. Rather than let that cross a file boundary, the
map is passed by nameref and the comments file by parameter, so
separate_code_and_comments fills what report_languages reads with no
global in between.

Two boundaries were one step off on the first pass and produced 23
shellcheck findings: the KEYWORDS_* tables and detect_languages had been
cut away from their only consumers, so every one read as unused (SC2034)
or unassigned (SC2154). Moving each beside its consumer cleared all 23
without a suppression. The nameref also makes shellcheck read a bare
assoc-array subscript on the left of an assignment as arithmetic;
quoting the nine keys is the fix.

The line-set diff against HEAD earned its place here: it caught a
`find ... -printf` call at original line 719 that had fallen into a
one-line gap between two extraction ranges and been dropped. bash -n and
shellcheck both passed on that broken version.

Verified without running the script (decision 6 -- install_missing_tools
calls sudo pacman, cargo and makepkg): shellcheck clean across all six,
the function set matches HEAD plus exactly the six new wrappers, no
executable line lost, and a stubbed run of the entry preamble defines
all fourteen functions, proving the source lines resolve at runtime.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
2026-08-16 21:47:03 +02:00

65 lines
5.1 KiB
JSON

{
"intent": "Bring analyze_repo.sh under the 250-line cap by splitting it into a thin entry script plus five sourced libs, leaving the analysis output it produces unchanged.",
"scope": [
"linux_configuration/scripts/single_use/utils/analyze_repo.sh (869 -> 231 lines)",
"New: lib/analyze_repo_{scan,tools,separate,report,symbols}.sh",
"Non-goal: running the script, which installs packages via sudo pacman / cargo / makepkg",
"Non-goal: defining the never-defined KEYWORDS_SHELL and KEYWORDS_JAVA tables"
],
"changes": [
"Extracted the output/discovery helpers (print_header, print_subheader, is_git_repo, find_files, count_files, fast_count) into lib/analyze_repo_scan.sh.",
"Extracted install_missing_tools, the 117-line package-manager dispatch, into lib/analyze_repo_tools.sh.",
"Wrapped the STEP 4 language-detection and comment/code-separation blocks as detect_languages and separate_code_and_comments in lib/analyze_repo_separate.sh; the HAS_* flags are set and read entirely within that file.",
"Wrapped the per-language keyword/function/import reporting as report_languages in lib/analyze_repo_report.sh, and moved the KEYWORDS_* tables in beside their only consumer.",
"Wrapped STEPs 5-7 as analyze_symbols, analyze_cscope and analyze_clang_ast in lib/analyze_repo_symbols.sh.",
"Passed the LANG_CODE_FILES map between the two STEP 4 passes explicitly by nameref and COMMENTS_TEMP by parameter, so no mutable state crosses a file boundary.",
"Fixed three unquoted $TOP_N expansions (SC2086) and quoted nine assoc-array subscripts that the nameref made shellcheck misread as arithmetic (SC2154). No suppression added."
],
"verification": [
{
"command": "shellcheck analyze_repo.sh lib/analyze_repo_*.sh",
"result": "pass",
"evidence": "Zero findings across all six files at the repo's no-severity-filter setting. An earlier boundary produced 23 findings (14 SC2034, 9 SC2154); those were cleared by moving the KEYWORDS_* tables and detect_languages beside their consumers, not by suppressing."
},
{
"command": "bash -n on the entry and each lib",
"result": "pass",
"evidence": "All six parse. Run before linting, per the heredoc trap in docs/shell-split-recipes.md."
},
{
"command": "bash ~/utils/scripts/check_file_length.sh --all",
"result": "pass",
"evidence": "entry 231, report 228, separate 186, tools 125, symbols 112, scan 86. None of the six appears in the violation list; repo total 69 -> 68."
},
{
"command": "diff of the function set against a detached worktree at HEAD",
"result": "pass",
"evidence": "All eight original functions preserved (count_files, fast_count, find_files, install_missing_tools, is_git_repo, is_url, print_header, print_subheader). The six additions are exactly the wrappers named in the contract. Each function is defined exactly once across the six files."
},
{
"command": "sorted line-set diff of HEAD:analyze_repo.sh against entry+libs concatenated",
"result": "pass",
"evidence": "After repair, no executable line is lost. The first pass caught a real regression this way: the `find \"$RESULTS_DIR/per_language/\" -maxdepth 1 -type f -printf` call at original line 719 fell into a one-line gap between two extraction ranges and was silently dropped. shellcheck and bash -n both passed on the broken version. Restored to the tail of report_languages."
},
{
"command": "stubbed run of the entry preamble (source lines only, main flow replaced by declare -F)",
"result": "pass",
"evidence": "Prints all fourteen function names, proving each source line resolves at runtime. verify_shell_split.sh does not apply here: the script has no main \"$@\", so the by-hand fallback in docs/shell-split-recipes.md was used."
},
{
"command": "grep -n 'source ' over the five libs",
"result": "pass",
"evidence": "No lib sources another; the entry sources all five. Only comment-text matches were returned."
}
],
"risks": [
"The script cannot be executed under decision 6, so verification is static plus a stubbed source. A behaviour change confined to the interior of a moved block would not be caught by the line-set diff, though that diff does prove no line was added, removed or reordered within a function body.",
"detect_languages now declares LANG_FILES as local rather than global. Confirmed safe: LANG_FILES was only ever read inside that same block. The HAS_* flags it sets remain global and are read by separate_code_and_comments in the same file.",
"The trap that cleans up COMMENTS_TEMP and /tmp/code_*.tmp moved into the entry script, where it is installed before the functions that create those files run. Same coverage as before, set one step earlier."
],
"rollback": [
"git revert the commit; analyze_repo.sh returns to its 869-line single-file form and the five libs disappear.",
"After rollback, re-run shellcheck on analyze_repo.sh to confirm it still lints clean, and confirm repo_to_study.sh still resolves ANALYZE_SCRIPT at scripts/single_use/utils/analyze_repo.sh, which this split did not move."
]
}