Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 8 additions & 6 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,14 @@ All notable changes to this project will be documented in this file.
### Changed

* Monolith de-layering (Step 11a): the network concern (status, diagnostics,
and connectivity actions — 17 functions) moved verbatim out of
`terminal/launchers/mqlaunch.sh` into `mqlaunch/lib/network.sh`, sourced back
into the launcher's scope. No behavior change; the launcher drops ~200 lines
and the concern now has a named owner. Guarded by
`tests/network-lib-delayer-smoke.sh`, which fails if a network function is
redefined in the monolith or the lib source is dropped.
and connectivity actions — 17 functions) and the fzf interactive pickers
(git log/branch, kill process/port, run snippet, recent files — 6 functions)
moved verbatim out of `terminal/launchers/mqlaunch.sh` into
`mqlaunch/lib/network.sh` and `mqlaunch/lib/fzf-pickers.sh`, sourced back into
the launcher's scope. No behavior change; the launcher drops ~310 lines and
each concern now has a named owner. Guarded by
`tests/monolith-delayer-smoke.sh`, a table-driven check that fails if any
extracted function is redefined in the monolith or a lib source is dropped.
* `semantic-memory-maintainer` renamed to `vector-store-maintainer` to avoid
routing collision with mq-mcp's skill of the same name.
* `command-template-library` skill moved to mq-ums, where the contracts and
Expand Down
1 change: 1 addition & 0 deletions docs/AUTHORITY_MAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ Reached through other live paths:
| `mqlaunch/lib/recommendations/*` | `terminal/menus/recommendations-menu.sh` |
| `mqlaunch/lib/mqobsidian/*` | `terminal/menus/mq-obsidian-menu.sh` |
| `mqlaunch/lib/network.sh` | `terminal/launchers/mqlaunch.sh` (sourced) — network concern de-layered out of the monolith (Step 11a) |
| `mqlaunch/lib/fzf-pickers.sh` | `terminal/launchers/mqlaunch.sh` (sourced) — fzf interactive pickers de-layered out of the monolith (Step 11a) |

## Bridges

Expand Down
131 changes: 131 additions & 0 deletions mqlaunch/lib/fzf-pickers.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
#!/usr/bin/env bash
# mqlaunch fzf pickers — interactive fuzzy finders for git, processes, ports,
# scripts, and recent files.
#
# Extracted from terminal/launchers/mqlaunch.sh as part of Step 11a (monolith
# de-layering, audit P4). Sourced into the launcher's scope, so it relies on the
# launcher's ambient UI helpers (print_header/row/print_footer/pause_enter) and
# $BASE_DIR. It defines no state of its own and changes no behavior — the
# functions are verbatim moves. Pure bash (no zsh builtins), so it carries a
# bash shebang and is covered by shellcheck.

# fzf: bläddra git log med diff-preview
fzf_git_log() {
local fzf_bin commit
fzf_bin="$(command -v fzf 2>/dev/null || true)"
[[ -z "$fzf_bin" ]] && echo "fzf not installed." && return 1
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "Inte i ett git-repo."
pause_enter
return 1
fi
commit="$(
git log --oneline --color=always | \
"$fzf_bin" --ansi --reverse --border \
--header='Git commits — Enter för att visa, Ctrl+C för att avbryta' \
--prompt='commit > ' \
--preview='git show --color=always {1}' \
--preview-window=right:60%
)"
[[ -z "$commit" ]] && return 0
git show "$(echo "$commit" | awk '{print $1}')"
pause_enter
}

# fzf: byt git-branch
fzf_git_branch() {
local fzf_bin branch
fzf_bin="$(command -v fzf 2>/dev/null || true)"
[[ -z "$fzf_bin" ]] && echo "fzf not installed." && return 1
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "Inte i ett git-repo."
pause_enter
return 1
fi
branch="$(
git branch --all | grep -v HEAD | sed 's/remotes\/origin\///' | sort -u | \
"$fzf_bin" --reverse --border \
--header='Välj branch att checka ut' \
--prompt='branch > '
)"
[[ -z "$branch" ]] && return 0
branch="$(echo "$branch" | xargs)"
git checkout "$branch"
pause_enter
}

# fzf: döda processer
fzf_kill_process() {
local fzf_bin selected pid
fzf_bin="$(command -v fzf 2>/dev/null || true)"
[[ -z "$fzf_bin" ]] && echo "fzf not installed." && return 1
selected="$(
ps aux | tail -n +2 | \
"$fzf_bin" --multi --reverse --border \
--header='Välj process(er) att döda — TAB för flerval' \
--prompt='process > '
)"
[[ -z "$selected" ]] && return 0
pid="$(echo "$selected" | awk '{print $2}')"
echo "$pid" | xargs kill -9 2>/dev/null
echo "Dödade PID: $(echo "$pid" | tr '\n' ' ')"
pause_enter
}

# fzf: döda process på port
fzf_kill_port() {
local fzf_bin selected pid port
fzf_bin="$(command -v fzf 2>/dev/null || true)"
[[ -z "$fzf_bin" ]] && echo "fzf not installed." && return 1
selected="$(
lsof -iTCP -sTCP:LISTEN -n -P 2>/dev/null | tail -n +2 | \
"$fzf_bin" --multi --reverse --border \
--header='Välj port(ar) att frigöra — TAB för flerval' \
--prompt='port > '
)"
[[ -z "$selected" ]] && return 0
pid="$(echo "$selected" | awk '{print $2}')"
port="$(echo "$selected" | awk '{print $9}' | cut -d: -f2 | tr '\n' ' ')"
echo "$pid" | xargs kill -9 2>/dev/null
echo "Frigjorde port(ar): $port"
pause_enter
}

# fzf: kör script från macos-scripts
fzf_run_snippet() {
local fzf_bin selected
fzf_bin="$(command -v fzf 2>/dev/null || true)"
[[ -z "$fzf_bin" ]] && echo "fzf not installed." && return 1
selected="$(
find "$BASE_DIR" -name "*.sh" -not -path "*/.git/*" -not -path "*/backups/*" 2>/dev/null | \
sed "s|$BASE_DIR/||" | sort | \
"$fzf_bin" --reverse --border \
--header='Välj script att köra' \
--prompt='script > ' \
--preview="bat --color=always '$BASE_DIR/{}' 2>/dev/null || cat '$BASE_DIR/{}'"
)"
[[ -z "$selected" ]] && return 0
print_header
row "Kör: $selected"
print_footer
bash "$BASE_DIR/$selected"
pause_enter
}

# fzf: visa och öppna nyligen ändrade filer
fzf_recent_files() {
local fzf_bin selected search_dir
fzf_bin="$(command -v fzf 2>/dev/null || true)"
[[ -z "$fzf_bin" ]] && echo "fzf not installed." && return 1
search_dir="${1:-$HOME/repos}"
selected="$(
find "$search_dir" -type f -not -path "*/.git/*" -newer "$search_dir" -mtime -14 2>/dev/null | \
sort | \
"$fzf_bin" --reverse --border \
--header='Senast ändrade filer (14 dagar) — Enter öppnar' \
--prompt='fil > ' \
--preview='bat --color=always {} 2>/dev/null || cat {}'
)"
[[ -z "$selected" ]] && return 0
"${EDITOR:-code}" "$selected" 2>/dev/null || open "$selected"
}
129 changes: 9 additions & 120 deletions terminal/launchers/mqlaunch.sh
Original file line number Diff line number Diff line change
Expand Up @@ -567,126 +567,15 @@ prompts_pick() {
fi
}

# fzf: bläddra git log med diff-preview
fzf_git_log() {
local fzf_bin commit
fzf_bin="$(command -v fzf 2>/dev/null || true)"
[[ -z "$fzf_bin" ]] && echo "fzf not installed." && return 1
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "Inte i ett git-repo."
pause_enter
return 1
fi
commit="$(
git log --oneline --color=always | \
"$fzf_bin" --ansi --reverse --border \
--header='Git commits — Enter för att visa, Ctrl+C för att avbryta' \
--prompt='commit > ' \
--preview='git show --color=always {1}' \
--preview-window=right:60%
)"
[[ -z "$commit" ]] && return 0
git show "$(echo "$commit" | awk '{print $1}')"
pause_enter
}

# fzf: byt git-branch
fzf_git_branch() {
local fzf_bin branch
fzf_bin="$(command -v fzf 2>/dev/null || true)"
[[ -z "$fzf_bin" ]] && echo "fzf not installed." && return 1
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "Inte i ett git-repo."
pause_enter
return 1
fi
branch="$(
git branch --all | grep -v HEAD | sed 's/remotes\/origin\///' | sort -u | \
"$fzf_bin" --reverse --border \
--header='Välj branch att checka ut' \
--prompt='branch > '
)"
[[ -z "$branch" ]] && return 0
branch="$(echo "$branch" | xargs)"
git checkout "$branch"
pause_enter
}

# fzf: döda processer
fzf_kill_process() {
local fzf_bin selected pid
fzf_bin="$(command -v fzf 2>/dev/null || true)"
[[ -z "$fzf_bin" ]] && echo "fzf not installed." && return 1
selected="$(
ps aux | tail -n +2 | \
"$fzf_bin" --multi --reverse --border \
--header='Välj process(er) att döda — TAB för flerval' \
--prompt='process > '
)"
[[ -z "$selected" ]] && return 0
pid="$(echo "$selected" | awk '{print $2}')"
echo "$pid" | xargs kill -9 2>/dev/null
echo "Dödade PID: $(echo "$pid" | tr '\n' ' ')"
pause_enter
}

# fzf: döda process på port
fzf_kill_port() {
local fzf_bin selected pid port
fzf_bin="$(command -v fzf 2>/dev/null || true)"
[[ -z "$fzf_bin" ]] && echo "fzf not installed." && return 1
selected="$(
lsof -iTCP -sTCP:LISTEN -n -P 2>/dev/null | tail -n +2 | \
"$fzf_bin" --multi --reverse --border \
--header='Välj port(ar) att frigöra — TAB för flerval' \
--prompt='port > '
)"
[[ -z "$selected" ]] && return 0
pid="$(echo "$selected" | awk '{print $2}')"
port="$(echo "$selected" | awk '{print $9}' | cut -d: -f2 | tr '\n' ' ')"
echo "$pid" | xargs kill -9 2>/dev/null
echo "Frigjorde port(ar): $port"
pause_enter
}

# fzf: kör script från macos-scripts
fzf_run_snippet() {
local fzf_bin selected
fzf_bin="$(command -v fzf 2>/dev/null || true)"
[[ -z "$fzf_bin" ]] && echo "fzf not installed." && return 1
selected="$(
find "$BASE_DIR" -name "*.sh" -not -path "*/.git/*" -not -path "*/backups/*" 2>/dev/null | \
sed "s|$BASE_DIR/||" | sort | \
"$fzf_bin" --reverse --border \
--header='Välj script att köra' \
--prompt='script > ' \
--preview="bat --color=always '$BASE_DIR/{}' 2>/dev/null || cat '$BASE_DIR/{}'"
)"
[[ -z "$selected" ]] && return 0
print_header
row "Kör: $selected"
print_footer
bash "$BASE_DIR/$selected"
pause_enter
}

# fzf: visa och öppna nyligen ändrade filer
fzf_recent_files() {
local fzf_bin selected search_dir
fzf_bin="$(command -v fzf 2>/dev/null || true)"
[[ -z "$fzf_bin" ]] && echo "fzf not installed." && return 1
search_dir="${1:-$HOME/repos}"
selected="$(
find "$search_dir" -type f -not -path "*/.git/*" -newer "$search_dir" -mtime -14 2>/dev/null | \
sort | \
"$fzf_bin" --reverse --border \
--header='Senast ändrade filer (14 dagar) — Enter öppnar' \
--prompt='fil > ' \
--preview='bat --color=always {} 2>/dev/null || cat {}'
)"
[[ -z "$selected" ]] && return 0
"${EDITOR:-code}" "$selected" 2>/dev/null || open "$selected"
}
# fzf interactive pickers (git log/branch, kill process/port, run snippet,
# recent files) live in a dedicated library (Step 11a monolith de-layering,
# audit P4). Sourced into this scope so they keep using the ambient UI helpers
# and $BASE_DIR; no behavior change — the functions are verbatim moves.
if [[ -f "$BASE_DIR/mqlaunch/lib/fzf-pickers.sh" ]]; then
source "$BASE_DIR/mqlaunch/lib/fzf-pickers.sh"
else
mq_debug "mqlaunch: fzf pickers lib missing: mqlaunch/lib/fzf-pickers.sh"
fi

# Opens repo browser.
open_repo_browser() {
Expand Down
51 changes: 51 additions & 0 deletions tests/monolith-delayer-smoke.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#!/usr/bin/env bash
# Smoke (P1 Step 11a): concerns de-layered out of the mqlaunch monolith stay
# out. For each extracted concern this guards the direction — every function is
# defined in its lib, the launcher sources that lib, and the launcher does not
# redefine any of them. A future edit that pulls a function back into
# mqlaunch.sh (or drops a lib source) fails here instead of silently
# re-monolithising. Add a row to CONCERNS as each new concern is extracted.
set -uo pipefail

ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
LAUNCHER="$ROOT/terminal/launchers/mqlaunch.sh"

fail() { printf '[FAIL] %s\n' "$1" >&2; exit 1; }

# Each concern: "lib_relpath : space-separated function names"
CONCERNS=(
"mqlaunch/lib/network.sh : network_default_interface network_service_name network_interface_ip network_dns_server network_gateway network_ssid network_ping_ms network_value network_report copy_network_info open_network_settings ping_test show_dns_gateway run_network_pulse run_network_ghost run_network_quality show_network_info"
"mqlaunch/lib/fzf-pickers.sh : fzf_git_log fzf_git_branch fzf_kill_process fzf_kill_port fzf_run_snippet fzf_recent_files"
)

total=0
for entry in "${CONCERNS[@]}"; do
lib_rel="${entry%% : *}"
funcs="${entry#* : }"
lib="$ROOT/$lib_rel"

[[ -f "$lib" ]] || fail "lib missing: $lib_rel"

# zsh-shebang libs get zsh -n; bash libs get bash -n. Both when tools exist.
shebang="$(head -1 "$lib")"
if [[ "$shebang" == *zsh* ]]; then
command -v zsh >/dev/null 2>&1 && { zsh -n "$lib" || fail "$lib_rel fails zsh -n"; }
else
bash -n "$lib" || fail "$lib_rel fails bash -n"
fi

# The launcher must source this lib.
grep -qF "source \"\$BASE_DIR/$lib_rel\"" "$LAUNCHER" \
|| fail "launcher no longer sources $lib_rel"

for f in $funcs; do
grep -qE "^${f}\(\) \{" "$lib" || fail "$lib_rel does not define $f"
if grep -qE "^${f}\(\) \{" "$LAUNCHER"; then
fail "launcher redefines $f — concern must stay in $lib_rel"
fi
total=$((total + 1))
done
done

printf '[PASS] monolith de-layering: %d functions across %d concern libs; launcher sources each, redefines none\n' \
"$total" "${#CONCERNS[@]}"
45 changes: 0 additions & 45 deletions tests/network-lib-delayer-smoke.sh

This file was deleted.

Loading
Loading