Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
7496ab7
Add CI lint gate and local precheck command
sbryngelson Feb 4, 2026
26f7e17
Fix precheck.sh portability and usability issues
sbryngelson Feb 4, 2026
4b17fa2
Gate benchmarks on Test Suite completion
sbryngelson Feb 4, 2026
1b211a5
Auto-install git pre-commit hook for precheck
sbryngelson Feb 4, 2026
9304137
Use dynamic CPU count in pre-commit hook
sbryngelson Feb 4, 2026
77ac8cc
Show CPU count in pre-commit hook output
sbryngelson Feb 4, 2026
a7cf1d2
Merge upstream master, resolve mfc.sh conflict
sbryngelson Feb 5, 2026
4b55c30
Add precheck command to CLI and autocomplete
sbryngelson Feb 5, 2026
e017cf0
Auto-update installed shell completions on regeneration
sbryngelson Feb 5, 2026
780138b
Show source command when completions auto-update
sbryngelson Feb 5, 2026
06f0425
Always check installed completions on every run
sbryngelson Feb 5, 2026
f65ed30
Prevent directory completion fallback in shell completions
sbryngelson Feb 5, 2026
d23addc
Auto-install completions and fix bash completion options
sbryngelson Feb 5, 2026
33cbd0e
Auto-install completions from mfc.sh with shell rc setup
sbryngelson Feb 5, 2026
1ba4666
Clarify verbose, debug, and debug-log flag documentation
sbryngelson Feb 5, 2026
adfcb7f
Cap pre-commit hook parallelism at 12 jobs
sbryngelson Feb 5, 2026
02ef3de
Fix completion auto-install to check for files, not just directory
sbryngelson Feb 5, 2026
ff8d499
Merge MFlowCode/MFC master into triage
sbryngelson Feb 5, 2026
fc5e2a5
Auto-update outdated shell completions
sbryngelson Feb 5, 2026
9c15c8a
Auto-activate completions when mfc.sh is sourced
sbryngelson Feb 5, 2026
52d0ddd
Use workflow_run for benchmarks and extract completion logic
sbryngelson Feb 5, 2026
8e3f405
Suppress verbose package list from uv install by default
sbryngelson Feb 5, 2026
989a79d
Compact splash screen from 45 to 20 lines
sbryngelson Feb 5, 2026
e913f7c
Pass arguments to python.sh for verbose flag support
sbryngelson Feb 5, 2026
6972e6e
Handle ./mfc.sh -v without command (show help, not error)
sbryngelson Feb 5, 2026
cf49bcc
Fix splash screen to use COMMANDS as single source of truth
sbryngelson Feb 5, 2026
72d8a38
Address AI reviewer feedback on PR #1124
sbryngelson Feb 5, 2026
88d8736
Show full build error output instead of truncating to 40 lines
sbryngelson Feb 5, 2026
c96edf2
Fix troubleshooting tips to suggest --debug instead of --debug-log
sbryngelson Feb 5, 2026
b44360f
Fix flags-before-command detection and shell detection
sbryngelson Feb 5, 2026
f24c62b
Raise minimum Python version to 3.12 (pyrometheus requires it)
sbryngelson Feb 5, 2026
e0bdc88
Lower minimum Python to 3.10 by pinning pyrometheus to pre-3.12 commit
sbryngelson Feb 5, 2026
f9fa919
Add -v flag to all CI build/run/test/bench commands
sbryngelson Feb 5, 2026
0ec406b
Add -v flag to coverage and GitHub runner CI commands
sbryngelson Feb 5, 2026
1e863ae
Revert pyrometheus pin to track git HEAD
sbryngelson Feb 5, 2026
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
8 changes: 4 additions & 4 deletions .github/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -50,16 +50,16 @@ RUN python3.12 -m venv /opt/MFC/build/venv && \
RUN echo "TARGET=$TARGET CC=$CC_COMPILER FC=$FC_COMPILER" && \
cd /opt/MFC && \
if [ "$TARGET" = "gpu" ]; then \
./mfc.sh build --gpu -j $(nproc); \
./mfc.sh build -v --gpu -j $(nproc); \
else \
./mfc.sh build -j $(nproc); \
./mfc.sh build -v -j $(nproc); \
fi

RUN cd /opt/MFC && \
if [ "$TARGET" = "gpu" ]; then \
./mfc.sh test -a --dry-run --gpu -j $(nproc); \
./mfc.sh test -v -a --dry-run --gpu -j $(nproc); \
else \
./mfc.sh test -a --dry-run -j $(nproc); \
./mfc.sh test -v -a --dry-run -j $(nproc); \
fi

WORKDIR /opt/MFC
Expand Down
101 changes: 50 additions & 51 deletions .github/workflows/bench.yml
Original file line number Diff line number Diff line change
@@ -1,87 +1,85 @@
name: 'Benchmark'

on:
pull_request:
pull_request_review:
types: [submitted]
# Trigger when Test Suite completes (no polling needed)
workflow_run:
workflows: ["Test Suite"]
types: [completed]
workflow_dispatch:

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
group: ${{ github.workflow }}-${{ github.event.workflow_run.head_branch || github.ref }}
cancel-in-progress: true

jobs:
file-changes:
name: Detect File Changes
# Only run if Test Suite passed (or manual dispatch)
if: github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success'
runs-on: 'ubuntu-latest'
outputs:
checkall: ${{ steps.changes.outputs.checkall }}
pr_number: ${{ steps.pr-info.outputs.pr_number }}
pr_approved: ${{ steps.pr-info.outputs.approved }}
pr_author: ${{ steps.pr-info.outputs.author }}
steps:
- name: Clone
uses: actions/checkout@v4
with:
ref: ${{ github.event.workflow_run.head_sha || github.sha }}

- name: Detect Changes
uses: dorny/paths-filter@v3
id: changes
with:
filters: ".github/file-filter.yml"

wait-for-tests:
name: Wait for Test Suite
runs-on: ubuntu-latest
steps:
- name: Wait for Test Suite to Pass
- name: Get PR Info
id: pr-info
env:
GH_TOKEN: ${{ github.token }}
run: |
echo "Waiting for Test Suite workflow to complete..."
SHA="${{ github.event.pull_request.head.sha || github.sha }}"

# Poll every 60 seconds for up to 3 hours
for i in $(seq 1 180); do
# Get the Test Suite workflow runs for this commit
STATUS=$(gh api repos/${{ github.repository }}/commits/$SHA/check-runs \
--jq '.check_runs[] | select(.name == "Lint Gate") | .conclusion' | head -1)

if [ "$STATUS" = "success" ]; then
echo "Lint Gate passed. Checking test jobs..."

# Check if any Github test jobs failed
FAILED=$(gh api repos/${{ github.repository }}/commits/$SHA/check-runs \
--jq '[.check_runs[] | select(.name | startswith("Github")) | select(.conclusion == "failure")] | length')

if [ "$FAILED" != "0" ]; then
echo "::error::Test Suite has failing jobs. Benchmarks will not run."
exit 1
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
echo "pr_number=" >> $GITHUB_OUTPUT
echo "approved=true" >> $GITHUB_OUTPUT
echo "author=${{ github.actor }}" >> $GITHUB_OUTPUT
else
# Get PR number from workflow_run
PR_NUMBER="${{ github.event.workflow_run.pull_requests[0].number }}"
if [ -n "$PR_NUMBER" ]; then
echo "pr_number=$PR_NUMBER" >> $GITHUB_OUTPUT

# Fetch actual PR author from API (workflow_run.actor is the re-runner, not PR author)
PR_AUTHOR=$(gh api repos/${{ github.repository }}/pulls/$PR_NUMBER --jq '.user.login')
echo "author=$PR_AUTHOR" >> $GITHUB_OUTPUT

# Check if PR is approved
APPROVED=$(gh api repos/${{ github.repository }}/pulls/$PR_NUMBER/reviews \
--jq '[.[] | select(.state == "APPROVED")] | length')
if [ "$APPROVED" -gt 0 ]; then
echo "approved=true" >> $GITHUB_OUTPUT
else
echo "approved=false" >> $GITHUB_OUTPUT
fi

# Check if Github tests are still running
PENDING=$(gh api repos/${{ github.repository }}/commits/$SHA/check-runs \
--jq '[.check_runs[] | select(.name | startswith("Github")) | select(.conclusion == null)] | length')

if [ "$PENDING" = "0" ]; then
echo "All Test Suite jobs completed successfully!"
exit 0
fi

echo "Tests still running ($PENDING pending)..."
elif [ "$STATUS" = "failure" ]; then
echo "::error::Lint Gate failed. Benchmarks will not run."
exit 1
else
echo "Lint Gate status: ${STATUS:-pending}..."
echo "pr_number=" >> $GITHUB_OUTPUT
echo "approved=false" >> $GITHUB_OUTPUT
echo "author=" >> $GITHUB_OUTPUT
fi

sleep 60
done

echo "::error::Timeout waiting for Test Suite to complete."
exit 1
fi

self:
name: "${{ matrix.name }} (${{ matrix.device }}${{ matrix.interface != 'none' && format('-{0}', matrix.interface) || '' }})"
if: ${{ github.repository=='MFlowCode/MFC' && needs.file-changes.outputs.checkall=='true' && ((github.event_name=='pull_request_review' && github.event.review.state=='approved') || (github.event_name=='pull_request' && (github.event.pull_request.user.login=='sbryngelson' || github.event.pull_request.user.login=='wilfonba'))) }}
needs: [file-changes, wait-for-tests]
if: >
github.repository == 'MFlowCode/MFC' &&
needs.file-changes.outputs.checkall == 'true' &&
(
github.event_name == 'workflow_dispatch' ||
needs.file-changes.outputs.pr_approved == 'true' ||
needs.file-changes.outputs.pr_author == 'sbryngelson' ||
needs.file-changes.outputs.pr_author == 'wilfonba'
)
needs: [file-changes]
strategy:
fail-fast: false
matrix:
Expand Down Expand Up @@ -145,6 +143,7 @@ jobs:
- name: Clone - PR
uses: actions/checkout@v4
with:
ref: ${{ github.event.workflow_run.head_sha || github.sha }}
path: pr

- name: Clone - Master
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,10 @@ jobs:
libfftw3-dev libhdf5-dev libblas-dev liblapack-dev

- name: Build
run: /bin/bash mfc.sh build -j $(nproc) --gcov
run: /bin/bash mfc.sh build -v -j $(nproc) --gcov

- name: Test
run: /bin/bash mfc.sh test -a -j $(nproc)
run: /bin/bash mfc.sh test -v -a -j $(nproc)
Comment on lines 41 to +45
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Fix actionlint SC2046 by quoting $(nproc).

actionlint flags the unquoted command substitution; this can fail the lint gate.

🔧 Suggested fix
-        run: /bin/bash mfc.sh build -v -j $(nproc) --gcov
+        run: /bin/bash mfc.sh build -v -j "$(nproc)" --gcov
@@
-        run: /bin/bash mfc.sh test -v -a -j $(nproc)
+        run: /bin/bash mfc.sh test -v -a -j "$(nproc)"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- name: Build
run: /bin/bash mfc.sh build -j $(nproc) --gcov
run: /bin/bash mfc.sh build -v -j $(nproc) --gcov
- name: Test
run: /bin/bash mfc.sh test -a -j $(nproc)
run: /bin/bash mfc.sh test -v -a -j $(nproc)
- name: Build
run: /bin/bash mfc.sh build -v -j "$(nproc)" --gcov
- name: Test
run: /bin/bash mfc.sh test -v -a -j "$(nproc)"
🧰 Tools
🪛 actionlint (1.7.10)

[error] 42-42: shellcheck reported issue in this script: SC2046:warning:1:30: Quote this to prevent word splitting

(shellcheck)


[error] 45-45: shellcheck reported issue in this script: SC2046:warning:1:32: Quote this to prevent word splitting

(shellcheck)

🤖 Prompt for AI Agents
In @.github/workflows/coverage.yml around lines 41 - 45, The workflow uses
unquoted command substitution for parallelism in the Build and Test steps (the
run lines invoking "mfc.sh build -v -j $(nproc) --gcov" and "mfc.sh test -v -a
-j $(nproc)"), which triggers actionlint SC2046; fix it by quoting the command
substitutions so they read "-j \"$(nproc)\"" in both the Build (mfc.sh build)
and Test (mfc.sh test) run commands to prevent word-splitting and satisfy
actionlint.


- name: Upload coverage reports to Codecov
uses: codecov/codecov-action@v4
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/frontier/bench.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ if [ "$job_device" = "gpu" ]; then
fi

if [ "$job_device" = "gpu" ]; then
./mfc.sh bench --mem 12 -j $n_ranks -o "$job_slug.yaml" -- -c frontier $device_opts -n $n_ranks
./mfc.sh bench -v --mem 12 -j $n_ranks -o "$job_slug.yaml" -- -c frontier $device_opts -n $n_ranks
else
./mfc.sh bench --mem 1 -j $(nproc) -o "$job_slug.yaml" -- -c frontier $device_opts -n $n_ranks
./mfc.sh bench -v --mem 1 -j $(nproc) -o "$job_slug.yaml" -- -c frontier $device_opts -n $n_ranks
fi
4 changes: 2 additions & 2 deletions .github/workflows/frontier/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ fi
if [ "$run_bench" == "bench" ]; then
for dir in benchmarks/*/; do
dirname=$(basename "$dir")
./mfc.sh run "$dir/case.py" --case-optimization -j 8 --dry-run $build_opts
./mfc.sh run -v "$dir/case.py" --case-optimization -j 8 --dry-run $build_opts
done
else
./mfc.sh test -a --dry-run --rdma-mpi -j 8 $build_opts
./mfc.sh test -v -a --dry-run --rdma-mpi -j 8 $build_opts
fi

4 changes: 2 additions & 2 deletions .github/workflows/frontier/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ if [ "$job_device" = "gpu" ]; then
fi

if [ "$job_device" = "gpu" ]; then
./mfc.sh test -a --rdma-mpi --max-attempts 3 -j $ngpus $device_opts -- -c frontier
./mfc.sh test -v -a --rdma-mpi --max-attempts 3 -j $ngpus $device_opts -- -c frontier
else
./mfc.sh test -a --max-attempts 3 -j 32 --no-gpu -- -c frontier
./mfc.sh test -v -a --max-attempts 3 -j 32 --no-gpu -- -c frontier
fi
4 changes: 2 additions & 2 deletions .github/workflows/frontier_amd/bench.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ if [ "$job_device" = "gpu" ]; then
fi

if [ "$job_device" = "gpu" ]; then
./mfc.sh bench --mem 12 -j $n_ranks -o "$job_slug.yaml" -- -c frontier_amd $device_opts -n $n_ranks
./mfc.sh bench -v --mem 12 -j $n_ranks -o "$job_slug.yaml" -- -c frontier_amd $device_opts -n $n_ranks
else
./mfc.sh bench --mem 1 -j $(nproc) -o "$job_slug.yaml" -- -c frontier_amd $device_opts -n $n_ranks
./mfc.sh bench -v --mem 1 -j $(nproc) -o "$job_slug.yaml" -- -c frontier_amd $device_opts -n $n_ranks
Comment on lines 18 to +21
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

rg -nP '\bjob_slug\b' -C2 .github/workflows

Repository: MFlowCode/MFC

Length of output: 10370


🏁 Script executed:

cat -n .github/workflows/frontier_amd/bench.sh | head -50

Repository: MFlowCode/MFC

Length of output: 1004


🏁 Script executed:

fd -type f -name "*.sh" .github/workflows | head -10

Repository: MFlowCode/MFC

Length of output: 227


🏁 Script executed:

cat -n .github/workflows/frontier_amd/submit-bench.sh

Repository: MFlowCode/MFC

Length of output: 1552


🏁 Script executed:

cat -n .github/workflows/frontier_amd/bench.sh

Repository: MFlowCode/MFC

Length of output: 1004


Quote variables to follow shellcheck recommendations.

Lines 19 and 21 use unquoted $n_ranks and $(nproc), which shellcheck flags for potential word-splitting issues. Quote these for consistency: "$n_ranks" and "$(nproc)".

Note: job_slug is reliably set in the parent sbatch context (submit-bench.sh line 45) before this script is sourced, so a guard is unnecessary.

🔧 Suggested fix
 if [ "$job_device" = "gpu" ]; then
-    ./mfc.sh bench -v --mem 12 -j $n_ranks -o "$job_slug.yaml" -- -c frontier_amd $device_opts -n $n_ranks
+    ./mfc.sh bench -v --mem 12 -j "$n_ranks" -o "$job_slug.yaml" -- -c frontier_amd $device_opts -n "$n_ranks"
 else
-    ./mfc.sh bench -v --mem 1 -j $(nproc) -o "$job_slug.yaml" -- -c frontier_amd $device_opts -n $n_ranks
+    ./mfc.sh bench -v --mem 1 -j "$(nproc)" -o "$job_slug.yaml" -- -c frontier_amd $device_opts -n "$n_ranks"
 fi
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if [ "$job_device" = "gpu" ]; then
./mfc.sh bench --mem 12 -j $n_ranks -o "$job_slug.yaml" -- -c frontier_amd $device_opts -n $n_ranks
./mfc.sh bench -v --mem 12 -j $n_ranks -o "$job_slug.yaml" -- -c frontier_amd $device_opts -n $n_ranks
else
./mfc.sh bench --mem 1 -j $(nproc) -o "$job_slug.yaml" -- -c frontier_amd $device_opts -n $n_ranks
./mfc.sh bench -v --mem 1 -j $(nproc) -o "$job_slug.yaml" -- -c frontier_amd $device_opts -n $n_ranks
if [ "$job_device" = "gpu" ]; then
./mfc.sh bench -v --mem 12 -j "$n_ranks" -o "$job_slug.yaml" -- -c frontier_amd $device_opts -n "$n_ranks"
else
./mfc.sh bench -v --mem 1 -j "$(nproc)" -o "$job_slug.yaml" -- -c frontier_amd $device_opts -n "$n_ranks"
fi
🧰 Tools
🪛 Shellcheck (0.11.0)

[warning] 19-19: job_slug is referenced but not assigned.

(SC2154)


[warning] 21-21: Quote this to prevent word splitting.

(SC2046)

🤖 Prompt for AI Agents
In @.github/workflows/frontier_amd/bench.sh around lines 18 - 21, ShellCheck
warns about unquoted variables causing word-splitting: in the bench invocation
inside the if/else branch (condition checks job_device and calls ./mfc.sh
bench), quote the $n_ranks and the command substitution $(nproc) so they become
"$n_ranks" and "$(nproc)"; update the two occurrences in the bench command lines
that call ./mfc.sh so the -j arguments are quoted, leaving job_device, job_slug
and device_opts usage unchanged.

fi
4 changes: 2 additions & 2 deletions .github/workflows/frontier_amd/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ fi
if [ "$run_bench" == "bench" ]; then
for dir in benchmarks/*/; do
dirname=$(basename "$dir")
./mfc.sh run "$dir/case.py" --case-optimization -j 8 --dry-run $build_opts
./mfc.sh run -v "$dir/case.py" --case-optimization -j 8 --dry-run $build_opts
done
else
./mfc.sh test -a --dry-run -j 8 $build_opts
./mfc.sh test -v -a --dry-run -j 8 $build_opts
fi

4 changes: 2 additions & 2 deletions .github/workflows/frontier_amd/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ if [ "$job_device" = "gpu" ]; then
fi

if [ "$job_device" = "gpu" ]; then
./mfc.sh test -a --max-attempts 3 -j $ngpus $device_opts -- -c frontier_amd
./mfc.sh test -v -a --max-attempts 3 -j $ngpus $device_opts -- -c frontier_amd
else
./mfc.sh test -a --max-attempts 3 -j 32 --no-gpu -- -c frontier_amd
./mfc.sh test -v -a --max-attempts 3 -j 32 --no-gpu -- -c frontier_amd
fi
4 changes: 2 additions & 2 deletions .github/workflows/phoenix/bench.sh
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ mkdir -p $currentdir
export TMPDIR=$currentdir

if [ "$job_device" = "gpu" ]; then
./mfc.sh bench --mem 12 -j $(nproc) -o "$job_slug.yaml" -- -c phoenix-bench $device_opts -n $n_ranks
./mfc.sh bench -v --mem 12 -j $(nproc) -o "$job_slug.yaml" -- -c phoenix-bench $device_opts -n $n_ranks
else
./mfc.sh bench --mem 1 -j $(nproc) -o "$job_slug.yaml" -- -c phoenix-bench $device_opts -n $n_ranks
./mfc.sh bench -v --mem 1 -j $(nproc) -o "$job_slug.yaml" -- -c phoenix-bench $device_opts -n $n_ranks
fi

sleep 10
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/phoenix/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ if [ "$job_device" = "gpu" ]; then
fi
fi

./mfc.sh test --dry-run -j 8 $build_opts
./mfc.sh test -v --dry-run -j 8 $build_opts

n_test_threads=8

Expand All @@ -21,5 +21,5 @@ if [ "$job_device" = "gpu" ]; then
n_test_threads=`expr $gpu_count \* 2`
fi

./mfc.sh test --max-attempts 3 -a -j $n_test_threads $device_opts -- -c phoenix
./mfc.sh test -v --max-attempts 3 -a -j $n_test_threads $device_opts -- -c phoenix

4 changes: 2 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -125,11 +125,11 @@ jobs:

- name: Build
run: |
/bin/bash mfc.sh test --dry-run -j $(nproc) --${{ matrix.debug }} --${{ matrix.mpi }} --${{ matrix.precision }}
/bin/bash mfc.sh test -v --dry-run -j $(nproc) --${{ matrix.debug }} --${{ matrix.mpi }} --${{ matrix.precision }}

- name: Test
run: |
/bin/bash mfc.sh test --max-attempts 3 -j $(nproc) $OPT1 $OPT2
/bin/bash mfc.sh test -v --max-attempts 3 -j $(nproc) $OPT1 $OPT2
env:
OPT1: ${{ matrix.mpi == 'mpi' && '--test-all' || '' }}
OPT2: ${{ matrix.debug == 'debug' && '-% 20' || '' }}
Expand Down
61 changes: 23 additions & 38 deletions mfc.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,32 +16,8 @@ if [ -d "$(pwd)/.git" ] && [ ! -e "$(pwd)/.git/hooks/pre-commit" ] && [ -f "$(pw
log "Installed git pre-commit hook (runs$MAGENTA ./mfc.sh precheck$COLOR_RESET before commits)."
fi

# Auto-install shell completions (once)
COMPLETION_DIR="$HOME/.local/share/mfc/completions"
if [ ! -d "$COMPLETION_DIR" ]; then
mkdir -p "$COMPLETION_DIR"
cp "$(pwd)/toolchain/completions/mfc.bash" "$COMPLETION_DIR/"
cp "$(pwd)/toolchain/completions/_mfc" "$COMPLETION_DIR/"

# Add to shell rc file based on current shell
if [[ "$SHELL" == *"zsh"* ]]; then
RC_FILE="$HOME/.zshrc"
RC_LINE="fpath=(\"$COMPLETION_DIR\" \$fpath)"
SOURCE_CMD="source $COMPLETION_DIR/_mfc"
else
RC_FILE="$HOME/.bashrc"
RC_LINE="[ -f \"$COMPLETION_DIR/mfc.bash\" ] && source \"$COMPLETION_DIR/mfc.bash\""
SOURCE_CMD="source $COMPLETION_DIR/mfc.bash"
fi

if [ -f "$RC_FILE" ] && ! grep -q "$COMPLETION_DIR" "$RC_FILE" 2>/dev/null; then
echo "" >> "$RC_FILE"
echo "# MFC shell completion" >> "$RC_FILE"
echo "$RC_LINE" >> "$RC_FILE"
fi

log "Installed tab completions. Restart shell or run:$MAGENTA $SOURCE_CMD$COLOR_RESET"
fi
# Shell completions auto-install/update
. "$(pwd)/toolchain/bootstrap/completions.sh" "$(pwd)"

# Print startup message immediately for user feedback
log "Starting..."
Expand Down Expand Up @@ -72,33 +48,33 @@ if [ "$1" '==' 'load' ] && [ "$2" != "--help" ] && [ "$2" != "-h" ]; then
echo ""
exit 1
fi
shift; . "$(pwd)/toolchain/bootstrap/modules.sh" $@; return
shift; . "$(pwd)/toolchain/bootstrap/modules.sh" "$@"; return
elif [ "$1" '==' "lint" ] && [ "$2" != "--help" ] && [ "$2" != "-h" ]; then
. "$(pwd)/toolchain/bootstrap/python.sh"
. "$(pwd)/toolchain/bootstrap/python.sh" "$@"

shift; . "$(pwd)/toolchain/bootstrap/lint.sh" $@; exit 0
shift; . "$(pwd)/toolchain/bootstrap/lint.sh" "$@"; exit 0
elif [ "$1" '==' "format" ] && [ "$2" != "--help" ] && [ "$2" != "-h" ]; then
. "$(pwd)/toolchain/bootstrap/python.sh"
. "$(pwd)/toolchain/bootstrap/python.sh" "$@"

shift; . "$(pwd)/toolchain/bootstrap/format.sh" $@; exit 0
shift; . "$(pwd)/toolchain/bootstrap/format.sh" "$@"; exit 0
elif [ "$1" '==' "venv" ]; then
shift; . "$(pwd)/toolchain/bootstrap/python.sh" $@; return
shift; . "$(pwd)/toolchain/bootstrap/python.sh" "$@"; return
elif [ "$1" '==' "clean" ] && [ "$2" != "--help" ] && [ "$2" != "-h" ]; then
rm -rf "$(pwd)/build"; exit 0
elif [ "$1" '==' "spelling" ] && [ "$2" != "--help" ] && [ "$2" != "-h" ]; then
. "$(pwd)/toolchain/bootstrap/python.sh"
. "$(pwd)/toolchain/bootstrap/python.sh" "$@"

shift; . "$(pwd)/toolchain/bootstrap/spelling.sh" $@; exit 0
shift; . "$(pwd)/toolchain/bootstrap/spelling.sh" "$@"; exit 0
elif [ "$1" '==' "precheck" ]; then
. "$(pwd)/toolchain/bootstrap/python.sh"
. "$(pwd)/toolchain/bootstrap/python.sh" "$@"

shift; . "$(pwd)/toolchain/bootstrap/precheck.sh" $@; exit 0
shift; . "$(pwd)/toolchain/bootstrap/precheck.sh" "$@"; exit 0
fi

mkdir -p "$(pwd)/build"

. "$(pwd)/toolchain/bootstrap/cmake.sh"
. "$(pwd)/toolchain/bootstrap/python.sh"
. "$(pwd)/toolchain/bootstrap/python.sh" "$@"

# init command: just bootstrap the environment and exit (no Python command)
if [ "$1" '==' 'init' ]; then
Expand All @@ -108,7 +84,16 @@ fi
echo

# Run the main.py bootstrap script
python3 "$(pwd)/toolchain/main.py" "$@"
# If only flags given (no command), show help without passing flags
has_command=false
for arg in "$@"; do
case "$arg" in -*) ;; *) has_command=true; break ;; esac
done
if [ "$has_command" = true ]; then
python3 "$(pwd)/toolchain/main.py" "$@"
else
python3 "$(pwd)/toolchain/main.py"
fi
code=$?

echo
Expand Down
Loading
Loading