From 1114eac892cb5eac4dc1003945f960c5913a93a6 Mon Sep 17 00:00:00 2001 From: Sall Date: Fri, 24 Jul 2026 09:09:16 +0100 Subject: [PATCH 1/5] chore: point renovate.json at next, add main-branch guard Same root cause found and fixed in z-shell/zsh-eza this session: renovate.json had no baseBranches override, so Renovate defaulted to main, bypassing next the same way several past PRs (#171, #150-156) did. dependabot.yml was already fixed for this in #172; this brings Renovate in line with it and ADR-0008 (z-shell/.github). Also adds a required-status-check workflow that fails a PR targeting main unless its head branch is next or matches hotfix-*. Closes #177 --- .github/workflows/main-branch-guard.yml | 30 +++++++++++++++++++++++++ renovate.json | 3 ++- 2 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/main-branch-guard.yml diff --git a/.github/workflows/main-branch-guard.yml b/.github/workflows/main-branch-guard.yml new file mode 100644 index 0000000..4f1468e --- /dev/null +++ b/.github/workflows/main-branch-guard.yml @@ -0,0 +1,30 @@ +--- +name: Main Branch Source Guard + +on: + pull_request: + branches: [main] + types: [opened, reopened, synchronize, edited] + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number }} + cancel-in-progress: true + +jobs: + guard: + name: Guard main branch source + runs-on: ubuntu-latest + steps: + - name: Verify pull request source branch + env: + HEAD_REF: ${{ github.head_ref }} + run: | + if [[ "${HEAD_REF}" == "next" || "${HEAD_REF}" == hotfix-* ]]; then + echo "Head branch '${HEAD_REF}' is allowed to target main." + exit 0 + fi + echo "::error::Pull requests into main must come from 'next' or a 'hotfix-*' branch (got '${HEAD_REF}'). See ADR-0008 (z-shell/.github) for the branching model." + exit 1 diff --git a/renovate.json b/renovate.json index fc1528e..c9dc506 100644 --- a/renovate.json +++ b/renovate.json @@ -4,5 +4,6 @@ "local>z-shell/.github:renovate-config", ":dependencyDashboardApproval", ":disableVulnerabilityAlerts" - ] + ], + "baseBranches": ["next"] } From 9633151802f3071312a90b90a702e6df8df0dea3 Mon Sep 17 00:00:00 2001 From: Sal Date: Sun, 16 Aug 2026 03:34:37 +0100 Subject: [PATCH 2/5] docs: add standard AGENTS.md and clean legacy ignore files --- .geminiignore | 0 .gitignore | 2 -- AGENTS.md | 16 ++++++++++++++++ 3 files changed, 16 insertions(+), 2 deletions(-) delete mode 100644 .geminiignore create mode 100644 AGENTS.md diff --git a/.geminiignore b/.geminiignore deleted file mode 100644 index e69de29..0000000 diff --git a/.gitignore b/.gitignore index 030f2a7..88784c4 100644 --- a/.gitignore +++ b/.gitignore @@ -150,7 +150,5 @@ worker/ node_modules/ .pnpm-store/ .cargo-ok -AGENTS.md CLAUDE.md GEMINI.md -.github/copilot-instructions.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..21cfcf0 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,16 @@ +# Project Guidelines — src + +This project follows the organization-wide [Z-Shell Organization Guidelines](https://github.com/z-shell/.github/blob/main/AGENTS.md). + +## What this is + +`src` contains the core Zi loader scripts, installer mechanisms, CDN assets, and sync utilities. + +## Conventions & Testing + +- Language: Zsh and POSIX sh. +- Follow `.github/instructions/zsh-scripting.instructions.md`. +- Verify installer and loader behavior with the test suite: + ```bash + make test || ./tests/run.sh + ``` From 8e2d4566863b9a19ab206be2866292459f596e94 Mon Sep 17 00:00:00 2001 From: Sal <59910950+ss-o@users.noreply.github.com> Date: Sun, 16 Aug 2026 10:58:40 +0100 Subject: [PATCH 3/5] fix: preserve init defaults under SH_WORD_SPLIT (#181) Co-authored-by: Sal --- public/checksum.txt | 4 ++-- public/sh/install.sh | 2 +- public/zsh/init.zsh | 22 +++++++++++----------- tests/installers.sh | 36 +++++++++++++++++++++++++++++++++++- 4 files changed, 49 insertions(+), 15 deletions(-) diff --git a/public/checksum.txt b/public/checksum.txt index 26ac375..899313f 100644 --- a/public/checksum.txt +++ b/public/checksum.txt @@ -1,4 +1,4 @@ 0140801e80b2d8767e95d215850b6feab3642ee2b6fd70fbf4aab09afcfe7fca public/sh/install_zpmod.sh -f9d8ef697ba682bdfe66fdd67d4517caa4e62bb8baf2868ec8ed9932809b76aa public/sh/install.sh +6ee1ced1b73ab9d6f8a17e26505dd5de588b2a0af2832603ae04eb2866763ed9 public/sh/install.sh 08cc893ceb982fc99d17db1966c6c30790cc571e16e4f5392352d995f5252952 public/sh/sync-init.sh -5c7af31d7fc848d80f9fedf69c75e6844503f550a3d5e020bc7cdfdaca624763 public/zsh/init.zsh +424d66dca9bc26dd225afa45ccf15e42c8cf1f9e5e68fa51b469969bb5d51901 public/zsh/init.zsh diff --git a/public/sh/install.sh b/public/sh/install.sh index 2062910..bd911bc 100755 --- a/public/sh/install.sh +++ b/public/sh/install.sh @@ -118,7 +118,7 @@ if [ "${AOPT}" = loader ]; then exit 1 fi # shellcheck disable=SC2016 - command sed 's|: ${ZI\[STREAM\]:="main"}|: ${ZI[STREAM]:="'"${BOPT}"'"}|' "${ZI_CONFIG_DIR}/init.zsh" >"${loader_tmp}" && + command sed 's|: "${ZI\[STREAM\]:=main}"|: "${ZI[STREAM]:='"${BOPT}"'}"|' "${ZI_CONFIG_DIR}/init.zsh" >"${loader_tmp}" && command mv "${loader_tmp}" "${ZI_CONFIG_DIR}/init.zsh" command chmod go-w "${ZI_CONFIG_DIR}" && command chmod a+x "${ZI_CONFIG_DIR}/init.zsh" fi diff --git a/public/zsh/init.zsh b/public/zsh/init.zsh index 74544ef..c72db20 100755 --- a/public/zsh/init.zsh +++ b/public/zsh/init.zsh @@ -13,21 +13,21 @@ typeset -ghA ZI # https://wiki.zshell.dev/docs/guides/customization -: ${ZI[REPOSITORY]:="https://github.com/z-shell/zi.git"} -: ${ZI[STREAM]:="main"} -: ${ZI[HOME_DIR]:="${XDG_DATA_HOME:-$HOME/.local/share}/zi"} -: ${ZI[BIN_DIR]:="${ZI[HOME_DIR]}/bin"} -: ${ZI[CACHE_DIR]:="${XDG_CACHE_HOME:-$HOME/.cache}/zi"} -: ${ZI[CONFIG_DIR]:="${XDG_CONFIG_HOME:-$HOME/.config}/zi"} +: "${ZI[REPOSITORY]:=https://github.com/z-shell/zi.git}" +: "${ZI[STREAM]:=main}" +: "${ZI[HOME_DIR]:=${XDG_DATA_HOME:-$HOME/.local/share}/zi}" +: "${ZI[BIN_DIR]:=${ZI[HOME_DIR]}/bin}" +: "${ZI[CACHE_DIR]:=${XDG_CACHE_HOME:-$HOME/.cache}/zi}" +: "${ZI[CONFIG_DIR]:=${XDG_CONFIG_HOME:-$HOME/.config}/zi}" # https://wiki.zshell.dev/community/zsh_plugin_standard#global-parameter-with-prefix -: ${ZPFX:=${ZI[HOME_DIR]}/polaris} -: ${ZI[ZMODULES_DIR]:=${ZI[HOME_DIR]}/zmodules} -: ${ZI[ZCOMPDUMP_PATH]:=${ZI[CACHE_DIR]}/.zcompdump} -: ${ZI[MUTE_WARNINGS]:=0} +: "${ZPFX:=${ZI[HOME_DIR]}/polaris}" +: "${ZI[ZMODULES_DIR]:=${ZI[HOME_DIR]}/zmodules}" +: "${ZI[ZCOMPDUMP_PATH]:=${ZI[CACHE_DIR]}/.zcompdump}" +: "${ZI[MUTE_WARNINGS]:=0}" # History defaults -: ${HISTFILE:=${XDG_STATE_HOME:-$HOME/.local/state}/zsh/history} +: "${HISTFILE:=${XDG_STATE_HOME:-$HOME/.local/state}/zsh/history}" [[ -e "$HISTFILE" ]] || { command mkdir -p "${HISTFILE:h}"; command touch "$HISTFILE"; } [[ -w "$HISTFILE" ]] && typeset -gx SAVEHIST=440000 HISTSIZE=441000 diff --git a/tests/installers.sh b/tests/installers.sh index 26a8418..48a0a27 100755 --- a/tests/installers.sh +++ b/tests/installers.sh @@ -64,6 +64,39 @@ check_checksums() { pass "checksums" } +test_init_defaults_are_single_arguments() { + capture_log="${TMP_ROOT}/init-default-arguments" + values_log="${TMP_ROOT}/init-default-values" + + zsh -f -c ' + capture_colon() { print -r -- "argc:$#" >>"$CAPTURE_LOG"; } + alias ":=capture_colon" + setopt aliases sh_word_split + typeset -A ZI + ZI[REPOSITORY]="repository with spaces" + export HOME="$4/home with spaces" + export XDG_DATA_HOME="$4/data root" + export XDG_CACHE_HOME="$4/cache root" + export XDG_CONFIG_HOME="$4/config root" + export XDG_STATE_HOME="$4/state root" + export CAPTURE_LOG="$2" + source "$1" + { + print -r -- "repository:${ZI[REPOSITORY]}" + print -r -- "home:${ZI[HOME_DIR]}" + print -r -- "history:${HISTFILE}" + } >"$3" + ' zsh "${ROOT}/public/zsh/init.zsh" "${capture_log}" "${values_log}" "${TMP_ROOT}" + + if grep -Fv 'argc:1' "${capture_log}" >/dev/null 2>&1; then + fail "init defaults were split into multiple arguments under SH_WORD_SPLIT" + fi + contains "${values_log}" 'repository:repository with spaces' + contains "${values_log}" "home:${TMP_ROOT}/data root/zi" + contains "${values_log}" "history:${TMP_ROOT}/state root/zsh/history" + pass "init defaults preserve argument and value boundaries" +} + write_fake_tools() { FAKE_BIN="${TMP_ROOT}/bin" command mkdir -p "${FAKE_BIN}" @@ -202,7 +235,7 @@ test_loader_install() { sh "${ROOT}/public/sh/install.sh" -a loader -b feature/test >/dev/null # shellcheck disable=SC2016 - contains "${config}/zi/init.zsh" ': ${ZI[STREAM]:="feature/test"}' + contains "${config}/zi/init.zsh" ': "${ZI[STREAM]:=feature/test}"' # shellcheck disable=SC2016 contains "${home}/.zshrc" 'source "${XDG_CONFIG_HOME:-${HOME}/.config}/zi/init.zsh" && zzinit' [ -f "${data}/zi/bin/zi.zsh" ] || fail "loader install did not clone Zi into XDG data home" @@ -344,6 +377,7 @@ test_sync_init() { check_syntax check_checksums +test_init_defaults_are_single_arguments write_fake_tools test_loader_install test_xdg_data_home_install From b8a5d39b9bb1b6cb77776628573a46e13b9bf99d Mon Sep 17 00:00:00 2001 From: Sal <59910950+ss-o@users.noreply.github.com> Date: Sun, 16 Aug 2026 12:05:06 +0100 Subject: [PATCH 4/5] ci: enforce zsh-lint reference corpus (#182) * ci: enforce zsh-lint reference corpus * fix(ci): pin deadlock-free zsh-lint workflow * fix(ci): disable zsh-lint workflow cache warnings --------- Co-authored-by: Sal --- .github/workflows/zsh-lint.yml | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 .github/workflows/zsh-lint.yml diff --git a/.github/workflows/zsh-lint.yml b/.github/workflows/zsh-lint.yml new file mode 100644 index 0000000..6a982ec --- /dev/null +++ b/.github/workflows/zsh-lint.yml @@ -0,0 +1,31 @@ +--- +name: Zsh Lint + +on: + push: + branches: [next, main] + paths: + - "public/zsh/init.zsh" + - ".github/workflows/zsh-lint.yml" + pull_request: + branches: [next, main] + paths: + - "public/zsh/init.zsh" + - ".github/workflows/zsh-lint.yml" + workflow_dispatch: {} + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + zsh-lint: + name: Zsh Lint + uses: z-shell/.github/.github/workflows/zsh-lint.yml@6dca2bef75c60106cde7237db5dea2c2eeed243b + with: + zsh-lint-ref: 3c4966b454fc07a346772a24d8311adab91414ed + paths: | + public/zsh/init.zsh From 95267f7a1559229ca0a30e4f96a6d2b9d68de326 Mon Sep 17 00:00:00 2001 From: Sal <59910950+ss-o@users.noreply.github.com> Date: Sun, 16 Aug 2026 13:01:11 +0100 Subject: [PATCH 5/5] chore: reconcile main into next (#183) Reconciles promoted changes from main back into next.