testsAndMisc/docs/superpowers/evidence/shell-extract-tool-2026-08-17.json
Krzysztof kuhy Rudnicki 94f4a5adb7
Some checks are pending
Pre-commit checks / pre-commit (push) Waiting to run
Python tests / test (push) Waiting to run
Shell tests / shell-tests (push) Waiting to run
Shell tests / arch-tests (push) Waiting to run
shell splits: add extract_shell_functions.py
Generalises the method proved on fresh-install/main.sh. Line-range slicing
is the obvious approach and it is wrong: these scripts interleave top-level
commands between their function definitions, so a range slice sweeps them
into the library where they run at source time and out of order. This walks
the file brace-by-brace, lifts only the function blocks, and leaves every
other line where it was.

Verified by re-deriving the already-committed main.sh split in a throwaway
worktree at HEAD~1: both files come out byte-for-byte identical to the
hand-made version that passed the shfmt harness, the structural flow
comparison, and the source-time side-effect check.

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

39 lines
2.6 KiB
JSON

{
"intent": "Generalise the fresh-install/main.sh split method into a reusable script, so the remaining shell splits do not repeat the line-range mistake that broke the first attempt.",
"scope": [
"New: meta/scripts/extract_shell_functions.py",
"Non-goal: any split; this commit only adds the tool"
],
"changes": [
"extract_shell_functions.py walks the script brace-by-brace, lifts only top-level function blocks (with the comment directly above each), and leaves every other line in place - so interleaved top-level commands cannot be swept into the library.",
"It inserts the source directive after the `set -e`/`set -euo pipefail` line, with a `# shellcheck source=` comment relative to the script's own directory, matching the repo convention for new sourced libs.",
"--functions moves a named subset, for scripts where only part of the body should leave.",
"It exits non-zero if a named function does not exist, or if there is no `set -e` line to anchor the source directive, rather than producing a subtly wrong file."
],
"verification": [
{
"command": "Re-derive the already-verified fresh-install/main.sh split in a throwaway worktree at HEAD~1, then diff against the committed result",
"result": "pass",
"evidence": "main.sh: IDENTICAL. lib/packages.sh: IDENTICAL. The tool reproduces byte-for-byte a split that was verified by hand with the shfmt harness, a structural flow comparison, and a source-time side-effect check."
},
{
"command": "python3 meta/scripts/extract_shell_functions.py --help",
"result": "pass",
"evidence": "Prints usage for script, library, --functions and --header."
},
{
"command": "pre-commit run --files meta/scripts/extract_shell_functions.py",
"result": "pass",
"evidence": "All hooks pass. A T201 print warning was fixed by writing to sys.stdout rather than suppressed."
}
],
"risks": [
"The brace counter treats { and } inside strings and heredocs as structural. A function containing an unbalanced brace in a string would be mis-delimited; verify_shell_split.sh reports the function count, so this shows up as a wrong count rather than silently.",
"It assumes the `name() {` form on one line. A script using `function name {` or a brace on the next line would have those functions ignored - again visible as a lower count in the verifier."
],
"rollback": [
"git revert the commit; the tool disappears and the already-committed splits are unaffected, since it only generates files.",
"No follow-up validation needed after rollback."
]
}