diff --git a/lib/hook-utils.sh b/lib/hook-utils.sh index 0776e2f766..41a9b28420 100644 --- a/lib/hook-utils.sh +++ b/lib/hook-utils.sh @@ -1443,26 +1443,30 @@ hook::git_resolve_index() { ;; sudo) # sudo's own chdir is -D/--chdir (its -C is close-from, -R is --chroot). - # Only the unclustered spellings are read here; sudo's valueless short set - # is large and release-dependent, so peeling a cluster the way the env - # branch does would be guesswork rather than grammar. - # Known gap, fail-open: a clustered `sudo -bD dir git …` loses the chdir, - # and `-i` relocates to the target user's home without naming a directory - # at all. + # GNU sudo clusters short options, so `-bD dir` carries a chdir that no + # exact `-D` match sees. Peel the documented valueless shorts (-A/-B/-b/-e/-E + # -H/-K/-k/-l/-n/-P/-s/-S/-v/-V, per `sudo --help`) off a single-dash token + # so the value-taking tail (-D/--chdir, -u/-g/-h/-p/-C/-R/-T) reaches its own + # branch. `-h` is value-taking (`-h host` / `--host=`) and must not be peeled. + # `-i` relocates to the target user's home without naming a directory at all. ((i++)) - local sudo_ci=-1 + local sudo_ci=-1 stok while ((i < n)) && [[ "${w[i]}" == -* ]]; do - case "${w[i]}" in + stok="${w[i]}" + if [[ "$stok" == -[!-]* ]]; then + while [[ "$stok" =~ ^-[ABbeEHKklnPsSvV](.+)$ ]]; do stok="-${BASH_REMATCH[1]}"; done + fi + case "$stok" in -D | --chdir) ((i + 1 < n)) && hook::wrapper_chdir_record sudo_ci "${w[i + 1]}" ((i += 2)) ;; --chdir=*) - hook::wrapper_chdir_record sudo_ci "${w[i]#--chdir=}" + hook::wrapper_chdir_record sudo_ci "${stok#--chdir=}" ((i++)) ;; -D*) - hook::wrapper_chdir_record sudo_ci "${w[i]#-D}" + hook::wrapper_chdir_record sudo_ci "${stok#-D}" ((i++)) ;; -u | -g | -h | -p | -C | -R | -T | --user | --group) ((i += 2)) ;; diff --git a/lib/hook-utils.test.sh b/lib/hook-utils.test.sh index b7a43a660f..7bb8a5bc7f 100755 --- a/lib/hook-utils.test.sh +++ b/lib/hook-utils.test.sh @@ -2163,6 +2163,10 @@ fi resolve_dirs_are "sudo -D DIR reports the chdir" "other" sudo -D other git commit resolve_dirs_are "sudo --chdir=DIR reports the chdir" "other" sudo --chdir=other git commit resolve_dirs_are "sudo -C fd is not a chdir" "" sudo -C 3 git commit +resolve_dirs_are "sudo -bD DIR peels the valueless short and reports the chdir" "other" sudo -bDother git commit +resolve_dirs_are "sudo -nD DIR peels -n and reports the chdir" "other" sudo -nDother git commit +resolve_dirs_are "sudo -AD DIR peels -A and reports the chdir" "other" sudo -ADother git commit +resolve_dirs_are "sudo -hD DIR does not peel -h and does not treat git as chdir" "" sudo -hD git commit # Nested wrappers each contribute, in execution order, for the caller to compose. resolve_dirs_are "nested wrappers report both chdirs in order" "a|b" env -C a sudo -D b git commit # `-S` exists so a shebang line can pass OPTIONS to env (`#!/usr/bin/env -S -i diff --git a/plugins/actionlint/.claude-plugin/plugin.json b/plugins/actionlint/.claude-plugin/plugin.json index a86e1d4749..a5d31308db 100644 --- a/plugins/actionlint/.claude-plugin/plugin.json +++ b/plugins/actionlint/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json", "name": "actionlint", - "version": "0.8.7", + "version": "0.8.9", "description": "Lint GitHub Actions workflow files on edit via actionlint, surfacing findings as advisory context.", "author": { "name": "Melodic Software", diff --git a/plugins/actionlint/CHANGELOG.md b/plugins/actionlint/CHANGELOG.md index d1cb9e9b43..13e77d2390 100644 --- a/plugins/actionlint/CHANGELOG.md +++ b/plugins/actionlint/CHANGELOG.md @@ -3,6 +3,18 @@ All notable changes to the `actionlint` plugin are documented here. Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); this plugin uses semantic versioning. +## [0.8.9] + +### Changed + +- **Synced `hook-utils.sh`:** peel sudo clustered short options for chdir resolution (#1811); widen the valueless-short peel set and keep `-h` value-taking. + +## [0.8.8] + +### Changed + +- **Synced `hook-utils.sh`:** peel sudo clustered short options for chdir resolution (#1811). + ## [0.8.7] ### Changed diff --git a/plugins/actionlint/hooks/hook-utils.sh b/plugins/actionlint/hooks/hook-utils.sh index 0776e2f766..41a9b28420 100644 --- a/plugins/actionlint/hooks/hook-utils.sh +++ b/plugins/actionlint/hooks/hook-utils.sh @@ -1443,26 +1443,30 @@ hook::git_resolve_index() { ;; sudo) # sudo's own chdir is -D/--chdir (its -C is close-from, -R is --chroot). - # Only the unclustered spellings are read here; sudo's valueless short set - # is large and release-dependent, so peeling a cluster the way the env - # branch does would be guesswork rather than grammar. - # Known gap, fail-open: a clustered `sudo -bD dir git …` loses the chdir, - # and `-i` relocates to the target user's home without naming a directory - # at all. + # GNU sudo clusters short options, so `-bD dir` carries a chdir that no + # exact `-D` match sees. Peel the documented valueless shorts (-A/-B/-b/-e/-E + # -H/-K/-k/-l/-n/-P/-s/-S/-v/-V, per `sudo --help`) off a single-dash token + # so the value-taking tail (-D/--chdir, -u/-g/-h/-p/-C/-R/-T) reaches its own + # branch. `-h` is value-taking (`-h host` / `--host=`) and must not be peeled. + # `-i` relocates to the target user's home without naming a directory at all. ((i++)) - local sudo_ci=-1 + local sudo_ci=-1 stok while ((i < n)) && [[ "${w[i]}" == -* ]]; do - case "${w[i]}" in + stok="${w[i]}" + if [[ "$stok" == -[!-]* ]]; then + while [[ "$stok" =~ ^-[ABbeEHKklnPsSvV](.+)$ ]]; do stok="-${BASH_REMATCH[1]}"; done + fi + case "$stok" in -D | --chdir) ((i + 1 < n)) && hook::wrapper_chdir_record sudo_ci "${w[i + 1]}" ((i += 2)) ;; --chdir=*) - hook::wrapper_chdir_record sudo_ci "${w[i]#--chdir=}" + hook::wrapper_chdir_record sudo_ci "${stok#--chdir=}" ((i++)) ;; -D*) - hook::wrapper_chdir_record sudo_ci "${w[i]#-D}" + hook::wrapper_chdir_record sudo_ci "${stok#-D}" ((i++)) ;; -u | -g | -h | -p | -C | -R | -T | --user | --group) ((i += 2)) ;; diff --git a/plugins/autonomy/.claude-plugin/plugin.json b/plugins/autonomy/.claude-plugin/plugin.json index 37ffc5f907..9d8181d69d 100644 --- a/plugins/autonomy/.claude-plugin/plugin.json +++ b/plugins/autonomy/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json", "name": "autonomy", - "version": "0.16.6", + "version": "0.16.7", "description": "Governed autonomous agent operation: role-topology, binding-seam, wiring-vs-advisor, telemetry, return-accounting, trigger-dispatch, per-work-class guardrail-matrix, standing-routine-catalog, and design-only runner-charter contracts for climbing the AI-adoption ladder, plus a guided-setup skill that discovers an adopting org's state, writes its schema-versioned binding, wires standards-pinned OTLP emission with a zero-cost file-artifact default, wires human-attested return capture at the task boundary, wires signal adapters with one governed dispatch entrypoint, binds the five-class guardrail matrix to an org's isolation substrates with an in-boundary live-validation probe before recording each fail-closed binding, and stands up standing-routine-catalog classes as scheduled temporal signal adapters behind the one governed queue with free scheduling defaults wired as reviewable changes and each routine's work-class mapping homed on the security surface.", "author": { "name": "Melodic Software", diff --git a/plugins/autonomy/CHANGELOG.md b/plugins/autonomy/CHANGELOG.md index 0ea29b3340..a3d62f0bd5 100644 --- a/plugins/autonomy/CHANGELOG.md +++ b/plugins/autonomy/CHANGELOG.md @@ -3,6 +3,12 @@ All notable changes to the `autonomy` plugin are documented here. Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); this plugin uses semantic versioning. +## [0.16.7] + +### Changed + +- **Synced `hook-utils.sh`:** peel sudo clustered short options for chdir resolution (#1811); widen the valueless-short peel set and keep `-h` value-taking. + ## [0.16.6] ### Fixed diff --git a/plugins/autonomy/hooks/hook-utils.sh b/plugins/autonomy/hooks/hook-utils.sh index 0776e2f766..41a9b28420 100644 --- a/plugins/autonomy/hooks/hook-utils.sh +++ b/plugins/autonomy/hooks/hook-utils.sh @@ -1443,26 +1443,30 @@ hook::git_resolve_index() { ;; sudo) # sudo's own chdir is -D/--chdir (its -C is close-from, -R is --chroot). - # Only the unclustered spellings are read here; sudo's valueless short set - # is large and release-dependent, so peeling a cluster the way the env - # branch does would be guesswork rather than grammar. - # Known gap, fail-open: a clustered `sudo -bD dir git …` loses the chdir, - # and `-i` relocates to the target user's home without naming a directory - # at all. + # GNU sudo clusters short options, so `-bD dir` carries a chdir that no + # exact `-D` match sees. Peel the documented valueless shorts (-A/-B/-b/-e/-E + # -H/-K/-k/-l/-n/-P/-s/-S/-v/-V, per `sudo --help`) off a single-dash token + # so the value-taking tail (-D/--chdir, -u/-g/-h/-p/-C/-R/-T) reaches its own + # branch. `-h` is value-taking (`-h host` / `--host=`) and must not be peeled. + # `-i` relocates to the target user's home without naming a directory at all. ((i++)) - local sudo_ci=-1 + local sudo_ci=-1 stok while ((i < n)) && [[ "${w[i]}" == -* ]]; do - case "${w[i]}" in + stok="${w[i]}" + if [[ "$stok" == -[!-]* ]]; then + while [[ "$stok" =~ ^-[ABbeEHKklnPsSvV](.+)$ ]]; do stok="-${BASH_REMATCH[1]}"; done + fi + case "$stok" in -D | --chdir) ((i + 1 < n)) && hook::wrapper_chdir_record sudo_ci "${w[i + 1]}" ((i += 2)) ;; --chdir=*) - hook::wrapper_chdir_record sudo_ci "${w[i]#--chdir=}" + hook::wrapper_chdir_record sudo_ci "${stok#--chdir=}" ((i++)) ;; -D*) - hook::wrapper_chdir_record sudo_ci "${w[i]#-D}" + hook::wrapper_chdir_record sudo_ci "${stok#-D}" ((i++)) ;; -u | -g | -h | -p | -C | -R | -T | --user | --group) ((i += 2)) ;; diff --git a/plugins/bash-format/.claude-plugin/plugin.json b/plugins/bash-format/.claude-plugin/plugin.json index c662aea452..841f48733c 100644 --- a/plugins/bash-format/.claude-plugin/plugin.json +++ b/plugins/bash-format/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json", "name": "bash-format", - "version": "0.7.9", + "version": "0.7.10", "description": "Auto-format and lint shell scripts on edit via shfmt + ShellCheck, using the consuming repo's own .editorconfig and .shellcheckrc.", "author": { "name": "Melodic Software", diff --git a/plugins/bash-format/CHANGELOG.md b/plugins/bash-format/CHANGELOG.md index 0ea336b3ea..b3351bda64 100644 --- a/plugins/bash-format/CHANGELOG.md +++ b/plugins/bash-format/CHANGELOG.md @@ -3,6 +3,12 @@ All notable changes to the `bash-format` plugin are documented here. Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); this plugin uses semantic versioning. +## [0.7.10] + +### Changed + +- **Synced `hook-utils.sh`:** peel sudo clustered short options for chdir resolution (#1811); widen the valueless-short peel set and keep `-h` value-taking. + ## [0.7.9] ### Added diff --git a/plugins/bash-format/hooks/hook-utils.sh b/plugins/bash-format/hooks/hook-utils.sh index 0776e2f766..41a9b28420 100644 --- a/plugins/bash-format/hooks/hook-utils.sh +++ b/plugins/bash-format/hooks/hook-utils.sh @@ -1443,26 +1443,30 @@ hook::git_resolve_index() { ;; sudo) # sudo's own chdir is -D/--chdir (its -C is close-from, -R is --chroot). - # Only the unclustered spellings are read here; sudo's valueless short set - # is large and release-dependent, so peeling a cluster the way the env - # branch does would be guesswork rather than grammar. - # Known gap, fail-open: a clustered `sudo -bD dir git …` loses the chdir, - # and `-i` relocates to the target user's home without naming a directory - # at all. + # GNU sudo clusters short options, so `-bD dir` carries a chdir that no + # exact `-D` match sees. Peel the documented valueless shorts (-A/-B/-b/-e/-E + # -H/-K/-k/-l/-n/-P/-s/-S/-v/-V, per `sudo --help`) off a single-dash token + # so the value-taking tail (-D/--chdir, -u/-g/-h/-p/-C/-R/-T) reaches its own + # branch. `-h` is value-taking (`-h host` / `--host=`) and must not be peeled. + # `-i` relocates to the target user's home without naming a directory at all. ((i++)) - local sudo_ci=-1 + local sudo_ci=-1 stok while ((i < n)) && [[ "${w[i]}" == -* ]]; do - case "${w[i]}" in + stok="${w[i]}" + if [[ "$stok" == -[!-]* ]]; then + while [[ "$stok" =~ ^-[ABbeEHKklnPsSvV](.+)$ ]]; do stok="-${BASH_REMATCH[1]}"; done + fi + case "$stok" in -D | --chdir) ((i + 1 < n)) && hook::wrapper_chdir_record sudo_ci "${w[i + 1]}" ((i += 2)) ;; --chdir=*) - hook::wrapper_chdir_record sudo_ci "${w[i]#--chdir=}" + hook::wrapper_chdir_record sudo_ci "${stok#--chdir=}" ((i++)) ;; -D*) - hook::wrapper_chdir_record sudo_ci "${w[i]#-D}" + hook::wrapper_chdir_record sudo_ci "${stok#-D}" ((i++)) ;; -u | -g | -h | -p | -C | -R | -T | --user | --group) ((i += 2)) ;; diff --git a/plugins/biome-format/.claude-plugin/plugin.json b/plugins/biome-format/.claude-plugin/plugin.json index f4c437df85..587650810e 100644 --- a/plugins/biome-format/.claude-plugin/plugin.json +++ b/plugins/biome-format/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json", "name": "biome-format", - "version": "0.6.8", + "version": "0.6.9", "description": "Auto-format and lint JS/TS/JSX/JSON on edit via Biome, only when a biome.json governs the repo \u2014 using the consuming repo's own Biome config.", "author": { "name": "Melodic Software", diff --git a/plugins/biome-format/CHANGELOG.md b/plugins/biome-format/CHANGELOG.md index 4dd675651c..8ec16416c3 100644 --- a/plugins/biome-format/CHANGELOG.md +++ b/plugins/biome-format/CHANGELOG.md @@ -3,6 +3,12 @@ All notable changes to the `biome-format` plugin are documented here. Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); this plugin uses semantic versioning. +## [0.6.9] + +### Changed + +- **Synced `hook-utils.sh`:** peel sudo clustered short options for chdir resolution (#1811); widen the valueless-short peel set and keep `-h` value-taking. + ## [0.6.8] ### Added diff --git a/plugins/biome-format/hooks/hook-utils.sh b/plugins/biome-format/hooks/hook-utils.sh index 0776e2f766..41a9b28420 100644 --- a/plugins/biome-format/hooks/hook-utils.sh +++ b/plugins/biome-format/hooks/hook-utils.sh @@ -1443,26 +1443,30 @@ hook::git_resolve_index() { ;; sudo) # sudo's own chdir is -D/--chdir (its -C is close-from, -R is --chroot). - # Only the unclustered spellings are read here; sudo's valueless short set - # is large and release-dependent, so peeling a cluster the way the env - # branch does would be guesswork rather than grammar. - # Known gap, fail-open: a clustered `sudo -bD dir git …` loses the chdir, - # and `-i` relocates to the target user's home without naming a directory - # at all. + # GNU sudo clusters short options, so `-bD dir` carries a chdir that no + # exact `-D` match sees. Peel the documented valueless shorts (-A/-B/-b/-e/-E + # -H/-K/-k/-l/-n/-P/-s/-S/-v/-V, per `sudo --help`) off a single-dash token + # so the value-taking tail (-D/--chdir, -u/-g/-h/-p/-C/-R/-T) reaches its own + # branch. `-h` is value-taking (`-h host` / `--host=`) and must not be peeled. + # `-i` relocates to the target user's home without naming a directory at all. ((i++)) - local sudo_ci=-1 + local sudo_ci=-1 stok while ((i < n)) && [[ "${w[i]}" == -* ]]; do - case "${w[i]}" in + stok="${w[i]}" + if [[ "$stok" == -[!-]* ]]; then + while [[ "$stok" =~ ^-[ABbeEHKklnPsSvV](.+)$ ]]; do stok="-${BASH_REMATCH[1]}"; done + fi + case "$stok" in -D | --chdir) ((i + 1 < n)) && hook::wrapper_chdir_record sudo_ci "${w[i + 1]}" ((i += 2)) ;; --chdir=*) - hook::wrapper_chdir_record sudo_ci "${w[i]#--chdir=}" + hook::wrapper_chdir_record sudo_ci "${stok#--chdir=}" ((i++)) ;; -D*) - hook::wrapper_chdir_record sudo_ci "${w[i]#-D}" + hook::wrapper_chdir_record sudo_ci "${stok#-D}" ((i++)) ;; -u | -g | -h | -p | -C | -R | -T | --user | --group) ((i += 2)) ;; diff --git a/plugins/claude-ops/.claude-plugin/plugin.json b/plugins/claude-ops/.claude-plugin/plugin.json index c54f220cf7..8b5d4679be 100644 --- a/plugins/claude-ops/.claude-plugin/plugin.json +++ b/plugins/claude-ops/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json", "name": "claude-ops", - "version": "0.31.3", + "version": "0.31.5", "description": "Claude Code operations toolkit. Ten skills: inventory (read-only enumeration of the complete invocable surface \u2014 every built-in CLI command with aliases and hidden/gated status, every bundled skill, and every component of every installed plugin across all marketplaces; reads the shipped binary because upstream publishes no built-in command list, and carries an integrity verdict so a drifted build reports counts as floors rather than silently short totals), audit-install-state (read-only audit of the machine-scope ~/.claude installation directory and ~/.claude.json \u2014 full inventory split into an authored surface and rolled-up bulk trees, product-managed retention vs genuinely unmanaged state, filename-scheme resolution before any process-liveness check, and deliberate/mid-experiment detection; reports, never deletes), audit-performance (read-only slowness-diagnostic capture run at the moment the machine or a session feels slow \u2014 CLI version, retention-sweep health including the silent unparsable-settings pause, a timed census walk of the install tree as a sweep-cost proxy, active-session and plugin-fleet counts, a process census, and a bundled known-performance-issues reference; separates the three documented suspects \u2014 accumulated state, version regression, component bloat \u2014 and routes remediation out; reports, never mutates), observability (read locally captured telemetry \u2014 OTEL store, collector, hook-event JSONL, ccusage \u2014 with trend reports and store pruning), known-issues (search known Claude product GitHub bugs, check service health, maintain a persistent tracked-issue registry), changelog (ingest Claude Code changelog entries and integrate them into the current repo), plugins (bring a machine's plugin fleet current on demand \u2014 marketplace refresh, effective-scope updates including in-repo project/local installs, new-plugin install per policy, scope-divergence detection and explicit convergence), morning-brief (read-only gh-based operator morning view \u2014 queue-label counts, merge-ready PRs, parked decisions with their RECOMMENDED lines, and loop-lane telemetry freshness), lanes (start/restart/stop/status loop lanes as named background Claude Code sessions seeded from canonical prompt files, with per-lane model/effort, a repo-pull + marketplace-refresh launch step, and a consume-restarts action \u2014 an OS-schedulable reader that relaunches stopped lanes whose telemetry carries a restart_request), and a re-runnable setup action that settles where the known-issues registry lives. Plus a family of seven advisory *-audit telemetry-emitter hooks (API errors, config changes, instruction loads, permission denials, pre-compaction, skill usage, tool failures) that emit the shared hook-telemetry envelope, and a reference sink that maps envelopes into the hook-events.jsonl the observability skill reads.", "author": { "name": "Melodic Software", diff --git a/plugins/claude-ops/CHANGELOG.md b/plugins/claude-ops/CHANGELOG.md index 7ad9cc0bca..1b44d98429 100644 --- a/plugins/claude-ops/CHANGELOG.md +++ b/plugins/claude-ops/CHANGELOG.md @@ -3,6 +3,18 @@ All notable changes to the `claude-ops` plugin are documented here. Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); this plugin uses semantic versioning. +## [0.31.5] + +### Changed + +- **Synced `hook-utils.sh`:** peel sudo clustered short options for chdir resolution (#1811); widen the valueless-short peel set and keep `-h` value-taking. + +## [0.31.4] + +### Changed + +- **Synced `hook-utils.sh`:** peel sudo clustered short options for chdir resolution (#1811). + ## [0.31.3] ### Changed diff --git a/plugins/claude-ops/hooks/hook-utils.sh b/plugins/claude-ops/hooks/hook-utils.sh index 0776e2f766..41a9b28420 100644 --- a/plugins/claude-ops/hooks/hook-utils.sh +++ b/plugins/claude-ops/hooks/hook-utils.sh @@ -1443,26 +1443,30 @@ hook::git_resolve_index() { ;; sudo) # sudo's own chdir is -D/--chdir (its -C is close-from, -R is --chroot). - # Only the unclustered spellings are read here; sudo's valueless short set - # is large and release-dependent, so peeling a cluster the way the env - # branch does would be guesswork rather than grammar. - # Known gap, fail-open: a clustered `sudo -bD dir git …` loses the chdir, - # and `-i` relocates to the target user's home without naming a directory - # at all. + # GNU sudo clusters short options, so `-bD dir` carries a chdir that no + # exact `-D` match sees. Peel the documented valueless shorts (-A/-B/-b/-e/-E + # -H/-K/-k/-l/-n/-P/-s/-S/-v/-V, per `sudo --help`) off a single-dash token + # so the value-taking tail (-D/--chdir, -u/-g/-h/-p/-C/-R/-T) reaches its own + # branch. `-h` is value-taking (`-h host` / `--host=`) and must not be peeled. + # `-i` relocates to the target user's home without naming a directory at all. ((i++)) - local sudo_ci=-1 + local sudo_ci=-1 stok while ((i < n)) && [[ "${w[i]}" == -* ]]; do - case "${w[i]}" in + stok="${w[i]}" + if [[ "$stok" == -[!-]* ]]; then + while [[ "$stok" =~ ^-[ABbeEHKklnPsSvV](.+)$ ]]; do stok="-${BASH_REMATCH[1]}"; done + fi + case "$stok" in -D | --chdir) ((i + 1 < n)) && hook::wrapper_chdir_record sudo_ci "${w[i + 1]}" ((i += 2)) ;; --chdir=*) - hook::wrapper_chdir_record sudo_ci "${w[i]#--chdir=}" + hook::wrapper_chdir_record sudo_ci "${stok#--chdir=}" ((i++)) ;; -D*) - hook::wrapper_chdir_record sudo_ci "${w[i]#-D}" + hook::wrapper_chdir_record sudo_ci "${stok#-D}" ((i++)) ;; -u | -g | -h | -p | -C | -R | -T | --user | --group) ((i += 2)) ;; diff --git a/plugins/context-guard/.claude-plugin/plugin.json b/plugins/context-guard/.claude-plugin/plugin.json index 8cd30a856c..b1a6818e92 100644 --- a/plugins/context-guard/.claude-plugin/plugin.json +++ b/plugins/context-guard/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json", "name": "context-guard", - "version": "0.7.5", + "version": "0.7.7", "description": "Per-session context-window observability plus the first shipped consumer: a statusline wrapper tees each session's context_window fields to a per-session snapshot file, a zone resolver classifies usage into smart/acceptable/dumb bands (percentage bands plus window-class token bands, conservative-min combination, zones.json SSOT with shipped defaults), a reader contract fixes how consuming sessions interpret the snapshots, and zone-crossing hooks report once per transition into a worse zone across two channels \u2014 the continuation menu to the operator, who owns that choice, and to the model only the zone determination plus the counter-steer that a zone word is not a decay signal (advisory by default; an optional blocking mode gates new mutating work on a fresh dumb-zone snapshot with handoff-writing exempt), with a PostCompact hook persisting an evidence-degraded marker.", "author": { "name": "Melodic Software", diff --git a/plugins/context-guard/CHANGELOG.md b/plugins/context-guard/CHANGELOG.md index 00c9d19a16..3bcfe555dd 100644 --- a/plugins/context-guard/CHANGELOG.md +++ b/plugins/context-guard/CHANGELOG.md @@ -5,6 +5,18 @@ All notable changes to the `context-guard` plugin. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.7.7] + +### Changed + +- **Synced `hook-utils.sh`:** peel sudo clustered short options for chdir resolution (#1811); widen the valueless-short peel set and keep `-h` value-taking. + +## [0.7.6] + +### Changed + +- **Synced `hook-utils.sh`:** peel sudo clustered short options for chdir resolution (#1811). + ## [0.7.5] ### Changed diff --git a/plugins/context-guard/hooks/hook-utils.sh b/plugins/context-guard/hooks/hook-utils.sh index 0776e2f766..41a9b28420 100755 --- a/plugins/context-guard/hooks/hook-utils.sh +++ b/plugins/context-guard/hooks/hook-utils.sh @@ -1443,26 +1443,30 @@ hook::git_resolve_index() { ;; sudo) # sudo's own chdir is -D/--chdir (its -C is close-from, -R is --chroot). - # Only the unclustered spellings are read here; sudo's valueless short set - # is large and release-dependent, so peeling a cluster the way the env - # branch does would be guesswork rather than grammar. - # Known gap, fail-open: a clustered `sudo -bD dir git …` loses the chdir, - # and `-i` relocates to the target user's home without naming a directory - # at all. + # GNU sudo clusters short options, so `-bD dir` carries a chdir that no + # exact `-D` match sees. Peel the documented valueless shorts (-A/-B/-b/-e/-E + # -H/-K/-k/-l/-n/-P/-s/-S/-v/-V, per `sudo --help`) off a single-dash token + # so the value-taking tail (-D/--chdir, -u/-g/-h/-p/-C/-R/-T) reaches its own + # branch. `-h` is value-taking (`-h host` / `--host=`) and must not be peeled. + # `-i` relocates to the target user's home without naming a directory at all. ((i++)) - local sudo_ci=-1 + local sudo_ci=-1 stok while ((i < n)) && [[ "${w[i]}" == -* ]]; do - case "${w[i]}" in + stok="${w[i]}" + if [[ "$stok" == -[!-]* ]]; then + while [[ "$stok" =~ ^-[ABbeEHKklnPsSvV](.+)$ ]]; do stok="-${BASH_REMATCH[1]}"; done + fi + case "$stok" in -D | --chdir) ((i + 1 < n)) && hook::wrapper_chdir_record sudo_ci "${w[i + 1]}" ((i += 2)) ;; --chdir=*) - hook::wrapper_chdir_record sudo_ci "${w[i]#--chdir=}" + hook::wrapper_chdir_record sudo_ci "${stok#--chdir=}" ((i++)) ;; -D*) - hook::wrapper_chdir_record sudo_ci "${w[i]#-D}" + hook::wrapper_chdir_record sudo_ci "${stok#-D}" ((i++)) ;; -u | -g | -h | -p | -C | -R | -T | --user | --group) ((i += 2)) ;; diff --git a/plugins/desktop-notification/.claude-plugin/plugin.json b/plugins/desktop-notification/.claude-plugin/plugin.json index df4c54c759..3f13358292 100644 --- a/plugins/desktop-notification/.claude-plugin/plugin.json +++ b/plugins/desktop-notification/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json", "name": "desktop-notification", - "version": "0.6.7", + "version": "0.6.9", "description": "Alert you when Claude Code needs input \u2014 an audible terminal bell, an OSC 9 terminal notification, and an OS-native toast (macOS/Linux) on permission and idle prompts.", "author": { "name": "Melodic Software", diff --git a/plugins/desktop-notification/CHANGELOG.md b/plugins/desktop-notification/CHANGELOG.md index d017e23fe7..f4badb7b8e 100644 --- a/plugins/desktop-notification/CHANGELOG.md +++ b/plugins/desktop-notification/CHANGELOG.md @@ -3,6 +3,18 @@ All notable changes to the `desktop-notification` plugin are documented here. Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); this plugin uses semantic versioning. +## [0.6.9] + +### Changed + +- **Synced `hook-utils.sh`:** peel sudo clustered short options for chdir resolution (#1811); widen the valueless-short peel set and keep `-h` value-taking. + +## [0.6.8] + +### Changed + +- **Synced `hook-utils.sh`:** peel sudo clustered short options for chdir resolution (#1811). + ## [0.6.7] ### Changed diff --git a/plugins/desktop-notification/hooks/hook-utils.sh b/plugins/desktop-notification/hooks/hook-utils.sh index 0776e2f766..41a9b28420 100644 --- a/plugins/desktop-notification/hooks/hook-utils.sh +++ b/plugins/desktop-notification/hooks/hook-utils.sh @@ -1443,26 +1443,30 @@ hook::git_resolve_index() { ;; sudo) # sudo's own chdir is -D/--chdir (its -C is close-from, -R is --chroot). - # Only the unclustered spellings are read here; sudo's valueless short set - # is large and release-dependent, so peeling a cluster the way the env - # branch does would be guesswork rather than grammar. - # Known gap, fail-open: a clustered `sudo -bD dir git …` loses the chdir, - # and `-i` relocates to the target user's home without naming a directory - # at all. + # GNU sudo clusters short options, so `-bD dir` carries a chdir that no + # exact `-D` match sees. Peel the documented valueless shorts (-A/-B/-b/-e/-E + # -H/-K/-k/-l/-n/-P/-s/-S/-v/-V, per `sudo --help`) off a single-dash token + # so the value-taking tail (-D/--chdir, -u/-g/-h/-p/-C/-R/-T) reaches its own + # branch. `-h` is value-taking (`-h host` / `--host=`) and must not be peeled. + # `-i` relocates to the target user's home without naming a directory at all. ((i++)) - local sudo_ci=-1 + local sudo_ci=-1 stok while ((i < n)) && [[ "${w[i]}" == -* ]]; do - case "${w[i]}" in + stok="${w[i]}" + if [[ "$stok" == -[!-]* ]]; then + while [[ "$stok" =~ ^-[ABbeEHKklnPsSvV](.+)$ ]]; do stok="-${BASH_REMATCH[1]}"; done + fi + case "$stok" in -D | --chdir) ((i + 1 < n)) && hook::wrapper_chdir_record sudo_ci "${w[i + 1]}" ((i += 2)) ;; --chdir=*) - hook::wrapper_chdir_record sudo_ci "${w[i]#--chdir=}" + hook::wrapper_chdir_record sudo_ci "${stok#--chdir=}" ((i++)) ;; -D*) - hook::wrapper_chdir_record sudo_ci "${w[i]#-D}" + hook::wrapper_chdir_record sudo_ci "${stok#-D}" ((i++)) ;; -u | -g | -h | -p | -C | -R | -T | --user | --group) ((i += 2)) ;; diff --git a/plugins/eol-normalizer/.claude-plugin/plugin.json b/plugins/eol-normalizer/.claude-plugin/plugin.json index c6ac3d1910..c04b9395ab 100644 --- a/plugins/eol-normalizer/.claude-plugin/plugin.json +++ b/plugins/eol-normalizer/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json", "name": "eol-normalizer", - "version": "0.6.7", + "version": "0.6.9", "description": "Normalize a written file's working-tree line endings to its .gitattributes eol value on edit \u2014 symmetric CRLF/LF driven by git check-attr, advisory and never blocking.", "author": { "name": "Melodic Software", diff --git a/plugins/eol-normalizer/CHANGELOG.md b/plugins/eol-normalizer/CHANGELOG.md index 6a22fa29f7..7c4bf260f0 100644 --- a/plugins/eol-normalizer/CHANGELOG.md +++ b/plugins/eol-normalizer/CHANGELOG.md @@ -3,6 +3,18 @@ All notable changes to the `eol-normalizer` plugin are documented here. Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); this plugin uses semantic versioning. +## [0.6.9] + +### Changed + +- **Synced `hook-utils.sh`:** peel sudo clustered short options for chdir resolution (#1811); widen the valueless-short peel set and keep `-h` value-taking. + +## [0.6.8] + +### Changed + +- **Synced `hook-utils.sh`:** peel sudo clustered short options for chdir resolution (#1811). + ## [0.6.7] ### Changed diff --git a/plugins/eol-normalizer/hooks/hook-utils.sh b/plugins/eol-normalizer/hooks/hook-utils.sh index 0776e2f766..41a9b28420 100644 --- a/plugins/eol-normalizer/hooks/hook-utils.sh +++ b/plugins/eol-normalizer/hooks/hook-utils.sh @@ -1443,26 +1443,30 @@ hook::git_resolve_index() { ;; sudo) # sudo's own chdir is -D/--chdir (its -C is close-from, -R is --chroot). - # Only the unclustered spellings are read here; sudo's valueless short set - # is large and release-dependent, so peeling a cluster the way the env - # branch does would be guesswork rather than grammar. - # Known gap, fail-open: a clustered `sudo -bD dir git …` loses the chdir, - # and `-i` relocates to the target user's home without naming a directory - # at all. + # GNU sudo clusters short options, so `-bD dir` carries a chdir that no + # exact `-D` match sees. Peel the documented valueless shorts (-A/-B/-b/-e/-E + # -H/-K/-k/-l/-n/-P/-s/-S/-v/-V, per `sudo --help`) off a single-dash token + # so the value-taking tail (-D/--chdir, -u/-g/-h/-p/-C/-R/-T) reaches its own + # branch. `-h` is value-taking (`-h host` / `--host=`) and must not be peeled. + # `-i` relocates to the target user's home without naming a directory at all. ((i++)) - local sudo_ci=-1 + local sudo_ci=-1 stok while ((i < n)) && [[ "${w[i]}" == -* ]]; do - case "${w[i]}" in + stok="${w[i]}" + if [[ "$stok" == -[!-]* ]]; then + while [[ "$stok" =~ ^-[ABbeEHKklnPsSvV](.+)$ ]]; do stok="-${BASH_REMATCH[1]}"; done + fi + case "$stok" in -D | --chdir) ((i + 1 < n)) && hook::wrapper_chdir_record sudo_ci "${w[i + 1]}" ((i += 2)) ;; --chdir=*) - hook::wrapper_chdir_record sudo_ci "${w[i]#--chdir=}" + hook::wrapper_chdir_record sudo_ci "${stok#--chdir=}" ((i++)) ;; -D*) - hook::wrapper_chdir_record sudo_ci "${w[i]#-D}" + hook::wrapper_chdir_record sudo_ci "${stok#-D}" ((i++)) ;; -u | -g | -h | -p | -C | -R | -T | --user | --group) ((i += 2)) ;; diff --git a/plugins/go-format/.claude-plugin/plugin.json b/plugins/go-format/.claude-plugin/plugin.json index 101d8effd1..ebb25fd110 100644 --- a/plugins/go-format/.claude-plugin/plugin.json +++ b/plugins/go-format/.claude-plugin/plugin.json @@ -1,8 +1,8 @@ { "$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json", "name": "go-format", - "version": "0.3.8", - "description": "Auto-fix Go formatting and import management on edit via goimports — runs unconditionally (no consumer-config gate), skipping generated files.", + "version": "0.3.10", + "description": "Auto-fix Go formatting and import management on edit via goimports \u2014 runs unconditionally (no consumer-config gate), skipping generated files.", "author": { "name": "Melodic Software", "email": "info@melodicsoftware.com" diff --git a/plugins/go-format/CHANGELOG.md b/plugins/go-format/CHANGELOG.md index e438718324..43b49e3a69 100644 --- a/plugins/go-format/CHANGELOG.md +++ b/plugins/go-format/CHANGELOG.md @@ -3,6 +3,18 @@ All notable changes to the `go-format` plugin are documented here. Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); this plugin uses semantic versioning. +## [0.3.10] + +### Changed + +- **Synced `hook-utils.sh`:** peel sudo clustered short options for chdir resolution (#1811); widen the valueless-short peel set and keep `-h` value-taking. + +## [0.3.9] + +### Changed + +- **Synced `hook-utils.sh`:** peel sudo clustered short options for chdir resolution (#1811). + ## [0.3.8] ### Added diff --git a/plugins/go-format/hooks/hook-utils.sh b/plugins/go-format/hooks/hook-utils.sh index 0776e2f766..41a9b28420 100644 --- a/plugins/go-format/hooks/hook-utils.sh +++ b/plugins/go-format/hooks/hook-utils.sh @@ -1443,26 +1443,30 @@ hook::git_resolve_index() { ;; sudo) # sudo's own chdir is -D/--chdir (its -C is close-from, -R is --chroot). - # Only the unclustered spellings are read here; sudo's valueless short set - # is large and release-dependent, so peeling a cluster the way the env - # branch does would be guesswork rather than grammar. - # Known gap, fail-open: a clustered `sudo -bD dir git …` loses the chdir, - # and `-i` relocates to the target user's home without naming a directory - # at all. + # GNU sudo clusters short options, so `-bD dir` carries a chdir that no + # exact `-D` match sees. Peel the documented valueless shorts (-A/-B/-b/-e/-E + # -H/-K/-k/-l/-n/-P/-s/-S/-v/-V, per `sudo --help`) off a single-dash token + # so the value-taking tail (-D/--chdir, -u/-g/-h/-p/-C/-R/-T) reaches its own + # branch. `-h` is value-taking (`-h host` / `--host=`) and must not be peeled. + # `-i` relocates to the target user's home without naming a directory at all. ((i++)) - local sudo_ci=-1 + local sudo_ci=-1 stok while ((i < n)) && [[ "${w[i]}" == -* ]]; do - case "${w[i]}" in + stok="${w[i]}" + if [[ "$stok" == -[!-]* ]]; then + while [[ "$stok" =~ ^-[ABbeEHKklnPsSvV](.+)$ ]]; do stok="-${BASH_REMATCH[1]}"; done + fi + case "$stok" in -D | --chdir) ((i + 1 < n)) && hook::wrapper_chdir_record sudo_ci "${w[i + 1]}" ((i += 2)) ;; --chdir=*) - hook::wrapper_chdir_record sudo_ci "${w[i]#--chdir=}" + hook::wrapper_chdir_record sudo_ci "${stok#--chdir=}" ((i++)) ;; -D*) - hook::wrapper_chdir_record sudo_ci "${w[i]#-D}" + hook::wrapper_chdir_record sudo_ci "${stok#-D}" ((i++)) ;; -u | -g | -h | -p | -C | -R | -T | --user | --group) ((i += 2)) ;; diff --git a/plugins/guardrails/.claude-plugin/plugin.json b/plugins/guardrails/.claude-plugin/plugin.json index a63cc4f343..f454d66ea3 100644 --- a/plugins/guardrails/.claude-plugin/plugin.json +++ b/plugins/guardrails/.claude-plugin/plugin.json @@ -135,5 +135,5 @@ "min": 1 } }, - "version": "0.28.11" + "version": "0.28.12" } diff --git a/plugins/guardrails/CHANGELOG.md b/plugins/guardrails/CHANGELOG.md index a8f9dbca64..07020b99b6 100644 --- a/plugins/guardrails/CHANGELOG.md +++ b/plugins/guardrails/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to the `guardrails` plugin are documented here. Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); this plugin uses semantic versioning. +## [0.28.12] + +### Fixed + +- **`hook::git_resolve_index` sudo cluster peel (#1811).** Peel documented valueless sudo + short options off clustered tokens so `sudo -bD git …` records the chdir; widen the + peel set to cover all documented valueless shorts while keeping `-h` value-taking. + ## [0.28.11] ### Fixed diff --git a/plugins/guardrails/hooks/hook-utils.sh b/plugins/guardrails/hooks/hook-utils.sh index 0776e2f766..41a9b28420 100644 --- a/plugins/guardrails/hooks/hook-utils.sh +++ b/plugins/guardrails/hooks/hook-utils.sh @@ -1443,26 +1443,30 @@ hook::git_resolve_index() { ;; sudo) # sudo's own chdir is -D/--chdir (its -C is close-from, -R is --chroot). - # Only the unclustered spellings are read here; sudo's valueless short set - # is large and release-dependent, so peeling a cluster the way the env - # branch does would be guesswork rather than grammar. - # Known gap, fail-open: a clustered `sudo -bD dir git …` loses the chdir, - # and `-i` relocates to the target user's home without naming a directory - # at all. + # GNU sudo clusters short options, so `-bD dir` carries a chdir that no + # exact `-D` match sees. Peel the documented valueless shorts (-A/-B/-b/-e/-E + # -H/-K/-k/-l/-n/-P/-s/-S/-v/-V, per `sudo --help`) off a single-dash token + # so the value-taking tail (-D/--chdir, -u/-g/-h/-p/-C/-R/-T) reaches its own + # branch. `-h` is value-taking (`-h host` / `--host=`) and must not be peeled. + # `-i` relocates to the target user's home without naming a directory at all. ((i++)) - local sudo_ci=-1 + local sudo_ci=-1 stok while ((i < n)) && [[ "${w[i]}" == -* ]]; do - case "${w[i]}" in + stok="${w[i]}" + if [[ "$stok" == -[!-]* ]]; then + while [[ "$stok" =~ ^-[ABbeEHKklnPsSvV](.+)$ ]]; do stok="-${BASH_REMATCH[1]}"; done + fi + case "$stok" in -D | --chdir) ((i + 1 < n)) && hook::wrapper_chdir_record sudo_ci "${w[i + 1]}" ((i += 2)) ;; --chdir=*) - hook::wrapper_chdir_record sudo_ci "${w[i]#--chdir=}" + hook::wrapper_chdir_record sudo_ci "${stok#--chdir=}" ((i++)) ;; -D*) - hook::wrapper_chdir_record sudo_ci "${w[i]#-D}" + hook::wrapper_chdir_record sudo_ci "${stok#-D}" ((i++)) ;; -u | -g | -h | -p | -C | -R | -T | --user | --group) ((i += 2)) ;; diff --git a/plugins/markdown-format/.claude-plugin/plugin.json b/plugins/markdown-format/.claude-plugin/plugin.json index 7f49af78a5..f66ac54bf2 100644 --- a/plugins/markdown-format/.claude-plugin/plugin.json +++ b/plugins/markdown-format/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json", "name": "markdown-format", - "version": "0.11.10", + "version": "0.11.12", "description": "Auto-format and lint Markdown on edit via markdownlint-cli2 \u2014 only in repos that carry their own markdownlint config.", "author": { "name": "Melodic Software", diff --git a/plugins/markdown-format/CHANGELOG.md b/plugins/markdown-format/CHANGELOG.md index 3051b816c7..a8496dfdbb 100644 --- a/plugins/markdown-format/CHANGELOG.md +++ b/plugins/markdown-format/CHANGELOG.md @@ -3,6 +3,18 @@ All notable changes to the `markdown-format` plugin are documented here. Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); this plugin uses semantic versioning. +## [0.11.12] + +### Changed + +- **Synced `hook-utils.sh`:** peel sudo clustered short options for chdir resolution (#1811); widen the valueless-short peel set and keep `-h` value-taking. + +## [0.11.11] + +### Changed + +- **Synced `hook-utils.sh`:** peel sudo clustered short options for chdir resolution (#1811). + ## [0.11.10] ### Changed diff --git a/plugins/markdown-format/hooks/hook-utils.sh b/plugins/markdown-format/hooks/hook-utils.sh index 0776e2f766..41a9b28420 100644 --- a/plugins/markdown-format/hooks/hook-utils.sh +++ b/plugins/markdown-format/hooks/hook-utils.sh @@ -1443,26 +1443,30 @@ hook::git_resolve_index() { ;; sudo) # sudo's own chdir is -D/--chdir (its -C is close-from, -R is --chroot). - # Only the unclustered spellings are read here; sudo's valueless short set - # is large and release-dependent, so peeling a cluster the way the env - # branch does would be guesswork rather than grammar. - # Known gap, fail-open: a clustered `sudo -bD dir git …` loses the chdir, - # and `-i` relocates to the target user's home without naming a directory - # at all. + # GNU sudo clusters short options, so `-bD dir` carries a chdir that no + # exact `-D` match sees. Peel the documented valueless shorts (-A/-B/-b/-e/-E + # -H/-K/-k/-l/-n/-P/-s/-S/-v/-V, per `sudo --help`) off a single-dash token + # so the value-taking tail (-D/--chdir, -u/-g/-h/-p/-C/-R/-T) reaches its own + # branch. `-h` is value-taking (`-h host` / `--host=`) and must not be peeled. + # `-i` relocates to the target user's home without naming a directory at all. ((i++)) - local sudo_ci=-1 + local sudo_ci=-1 stok while ((i < n)) && [[ "${w[i]}" == -* ]]; do - case "${w[i]}" in + stok="${w[i]}" + if [[ "$stok" == -[!-]* ]]; then + while [[ "$stok" =~ ^-[ABbeEHKklnPsSvV](.+)$ ]]; do stok="-${BASH_REMATCH[1]}"; done + fi + case "$stok" in -D | --chdir) ((i + 1 < n)) && hook::wrapper_chdir_record sudo_ci "${w[i + 1]}" ((i += 2)) ;; --chdir=*) - hook::wrapper_chdir_record sudo_ci "${w[i]#--chdir=}" + hook::wrapper_chdir_record sudo_ci "${stok#--chdir=}" ((i++)) ;; -D*) - hook::wrapper_chdir_record sudo_ci "${w[i]#-D}" + hook::wrapper_chdir_record sudo_ci "${stok#-D}" ((i++)) ;; -u | -g | -h | -p | -C | -R | -T | --user | --group) ((i += 2)) ;; diff --git a/plugins/powershell-format/.claude-plugin/plugin.json b/plugins/powershell-format/.claude-plugin/plugin.json index 2ccc6d8499..dbcf42bfaf 100644 --- a/plugins/powershell-format/.claude-plugin/plugin.json +++ b/plugins/powershell-format/.claude-plugin/plugin.json @@ -1,8 +1,8 @@ { "$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json", "name": "powershell-format", - "version": "0.7.9", - "description": "Auto-format and lint PowerShell on edit via PSScriptAnalyzer, only when a PSScriptAnalyzerSettings.psd1 governs the repo — using the consuming repo's own analyzer settings.", + "version": "0.7.10", + "description": "Auto-format and lint PowerShell on edit via PSScriptAnalyzer, only when a PSScriptAnalyzerSettings.psd1 governs the repo \u2014 using the consuming repo's own analyzer settings.", "author": { "name": "Melodic Software", "email": "info@melodicsoftware.com" diff --git a/plugins/powershell-format/CHANGELOG.md b/plugins/powershell-format/CHANGELOG.md index 55d11e4a42..7c1566d8d6 100644 --- a/plugins/powershell-format/CHANGELOG.md +++ b/plugins/powershell-format/CHANGELOG.md @@ -3,6 +3,12 @@ All notable changes to the `powershell-format` plugin are documented here. Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); this plugin uses semantic versioning. +## [0.7.10] + +### Changed + +- **Synced `hook-utils.sh`:** peel sudo clustered short options for chdir resolution (#1811); widen the valueless-short peel set and keep `-h` value-taking. + ## [0.7.9] ### Added diff --git a/plugins/powershell-format/hooks/hook-utils.sh b/plugins/powershell-format/hooks/hook-utils.sh index 0776e2f766..41a9b28420 100644 --- a/plugins/powershell-format/hooks/hook-utils.sh +++ b/plugins/powershell-format/hooks/hook-utils.sh @@ -1443,26 +1443,30 @@ hook::git_resolve_index() { ;; sudo) # sudo's own chdir is -D/--chdir (its -C is close-from, -R is --chroot). - # Only the unclustered spellings are read here; sudo's valueless short set - # is large and release-dependent, so peeling a cluster the way the env - # branch does would be guesswork rather than grammar. - # Known gap, fail-open: a clustered `sudo -bD dir git …` loses the chdir, - # and `-i` relocates to the target user's home without naming a directory - # at all. + # GNU sudo clusters short options, so `-bD dir` carries a chdir that no + # exact `-D` match sees. Peel the documented valueless shorts (-A/-B/-b/-e/-E + # -H/-K/-k/-l/-n/-P/-s/-S/-v/-V, per `sudo --help`) off a single-dash token + # so the value-taking tail (-D/--chdir, -u/-g/-h/-p/-C/-R/-T) reaches its own + # branch. `-h` is value-taking (`-h host` / `--host=`) and must not be peeled. + # `-i` relocates to the target user's home without naming a directory at all. ((i++)) - local sudo_ci=-1 + local sudo_ci=-1 stok while ((i < n)) && [[ "${w[i]}" == -* ]]; do - case "${w[i]}" in + stok="${w[i]}" + if [[ "$stok" == -[!-]* ]]; then + while [[ "$stok" =~ ^-[ABbeEHKklnPsSvV](.+)$ ]]; do stok="-${BASH_REMATCH[1]}"; done + fi + case "$stok" in -D | --chdir) ((i + 1 < n)) && hook::wrapper_chdir_record sudo_ci "${w[i + 1]}" ((i += 2)) ;; --chdir=*) - hook::wrapper_chdir_record sudo_ci "${w[i]#--chdir=}" + hook::wrapper_chdir_record sudo_ci "${stok#--chdir=}" ((i++)) ;; -D*) - hook::wrapper_chdir_record sudo_ci "${w[i]#-D}" + hook::wrapper_chdir_record sudo_ci "${stok#-D}" ((i++)) ;; -u | -g | -h | -p | -C | -R | -T | --user | --group) ((i += 2)) ;; diff --git a/plugins/rate-limit-guard/.claude-plugin/plugin.json b/plugins/rate-limit-guard/.claude-plugin/plugin.json index 08698fe13c..d73f5dbb22 100644 --- a/plugins/rate-limit-guard/.claude-plugin/plugin.json +++ b/plugins/rate-limit-guard/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json", "name": "rate-limit-guard", - "version": "0.6.1", + "version": "0.6.2", "description": "Shared rate-limit guard for loop lanes: a statusline wrapper tees the subscription rate-limit windows to a fixed machine-scope file, a StopFailure hook records rate-limit stops reactively, and a reader contract fixes how consuming sessions pause and resume.", "author": { "name": "Melodic Software", diff --git a/plugins/rate-limit-guard/CHANGELOG.md b/plugins/rate-limit-guard/CHANGELOG.md index 111f524a24..ee118f01fd 100644 --- a/plugins/rate-limit-guard/CHANGELOG.md +++ b/plugins/rate-limit-guard/CHANGELOG.md @@ -3,6 +3,12 @@ All notable changes to the `rate-limit-guard` plugin are documented here. Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); this plugin uses semantic versioning. +## [0.6.2] + +### Changed + +- **Synced `hook-utils.sh`:** peel sudo clustered short options for chdir resolution (#1811); widen the valueless-short peel set and keep `-h` value-taking. + ## [0.6.1] ### Changed diff --git a/plugins/rate-limit-guard/hooks/hook-utils.sh b/plugins/rate-limit-guard/hooks/hook-utils.sh index 0776e2f766..41a9b28420 100755 --- a/plugins/rate-limit-guard/hooks/hook-utils.sh +++ b/plugins/rate-limit-guard/hooks/hook-utils.sh @@ -1443,26 +1443,30 @@ hook::git_resolve_index() { ;; sudo) # sudo's own chdir is -D/--chdir (its -C is close-from, -R is --chroot). - # Only the unclustered spellings are read here; sudo's valueless short set - # is large and release-dependent, so peeling a cluster the way the env - # branch does would be guesswork rather than grammar. - # Known gap, fail-open: a clustered `sudo -bD dir git …` loses the chdir, - # and `-i` relocates to the target user's home without naming a directory - # at all. + # GNU sudo clusters short options, so `-bD dir` carries a chdir that no + # exact `-D` match sees. Peel the documented valueless shorts (-A/-B/-b/-e/-E + # -H/-K/-k/-l/-n/-P/-s/-S/-v/-V, per `sudo --help`) off a single-dash token + # so the value-taking tail (-D/--chdir, -u/-g/-h/-p/-C/-R/-T) reaches its own + # branch. `-h` is value-taking (`-h host` / `--host=`) and must not be peeled. + # `-i` relocates to the target user's home without naming a directory at all. ((i++)) - local sudo_ci=-1 + local sudo_ci=-1 stok while ((i < n)) && [[ "${w[i]}" == -* ]]; do - case "${w[i]}" in + stok="${w[i]}" + if [[ "$stok" == -[!-]* ]]; then + while [[ "$stok" =~ ^-[ABbeEHKklnPsSvV](.+)$ ]]; do stok="-${BASH_REMATCH[1]}"; done + fi + case "$stok" in -D | --chdir) ((i + 1 < n)) && hook::wrapper_chdir_record sudo_ci "${w[i + 1]}" ((i += 2)) ;; --chdir=*) - hook::wrapper_chdir_record sudo_ci "${w[i]#--chdir=}" + hook::wrapper_chdir_record sudo_ci "${stok#--chdir=}" ((i++)) ;; -D*) - hook::wrapper_chdir_record sudo_ci "${w[i]#-D}" + hook::wrapper_chdir_record sudo_ci "${stok#-D}" ((i++)) ;; -u | -g | -h | -p | -C | -R | -T | --user | --group) ((i += 2)) ;; diff --git a/plugins/ruff-format/.claude-plugin/plugin.json b/plugins/ruff-format/.claude-plugin/plugin.json index 6aa4800996..f0e0aff9b8 100644 --- a/plugins/ruff-format/.claude-plugin/plugin.json +++ b/plugins/ruff-format/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json", "name": "ruff-format", - "version": "0.6.8", + "version": "0.6.10", "description": "Auto-format and lint Python on edit via Ruff, only when a Ruff config governs the repo \u2014 using the consuming repo's own Ruff config.", "author": { "name": "Melodic Software", diff --git a/plugins/ruff-format/CHANGELOG.md b/plugins/ruff-format/CHANGELOG.md index 6a35e5a3fe..80221b8ce8 100644 --- a/plugins/ruff-format/CHANGELOG.md +++ b/plugins/ruff-format/CHANGELOG.md @@ -3,6 +3,18 @@ All notable changes to the `ruff-format` plugin are documented here. Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); this plugin uses semantic versioning. +## [0.6.10] + +### Changed + +- **Synced `hook-utils.sh`:** peel sudo clustered short options for chdir resolution (#1811); widen the valueless-short peel set and keep `-h` value-taking. + +## [0.6.9] + +### Changed + +- **Synced `hook-utils.sh`:** peel sudo clustered short options for chdir resolution (#1811). + ## [0.6.8] ### Added diff --git a/plugins/ruff-format/hooks/hook-utils.sh b/plugins/ruff-format/hooks/hook-utils.sh index 0776e2f766..41a9b28420 100644 --- a/plugins/ruff-format/hooks/hook-utils.sh +++ b/plugins/ruff-format/hooks/hook-utils.sh @@ -1443,26 +1443,30 @@ hook::git_resolve_index() { ;; sudo) # sudo's own chdir is -D/--chdir (its -C is close-from, -R is --chroot). - # Only the unclustered spellings are read here; sudo's valueless short set - # is large and release-dependent, so peeling a cluster the way the env - # branch does would be guesswork rather than grammar. - # Known gap, fail-open: a clustered `sudo -bD dir git …` loses the chdir, - # and `-i` relocates to the target user's home without naming a directory - # at all. + # GNU sudo clusters short options, so `-bD dir` carries a chdir that no + # exact `-D` match sees. Peel the documented valueless shorts (-A/-B/-b/-e/-E + # -H/-K/-k/-l/-n/-P/-s/-S/-v/-V, per `sudo --help`) off a single-dash token + # so the value-taking tail (-D/--chdir, -u/-g/-h/-p/-C/-R/-T) reaches its own + # branch. `-h` is value-taking (`-h host` / `--host=`) and must not be peeled. + # `-i` relocates to the target user's home without naming a directory at all. ((i++)) - local sudo_ci=-1 + local sudo_ci=-1 stok while ((i < n)) && [[ "${w[i]}" == -* ]]; do - case "${w[i]}" in + stok="${w[i]}" + if [[ "$stok" == -[!-]* ]]; then + while [[ "$stok" =~ ^-[ABbeEHKklnPsSvV](.+)$ ]]; do stok="-${BASH_REMATCH[1]}"; done + fi + case "$stok" in -D | --chdir) ((i + 1 < n)) && hook::wrapper_chdir_record sudo_ci "${w[i + 1]}" ((i += 2)) ;; --chdir=*) - hook::wrapper_chdir_record sudo_ci "${w[i]#--chdir=}" + hook::wrapper_chdir_record sudo_ci "${stok#--chdir=}" ((i++)) ;; -D*) - hook::wrapper_chdir_record sudo_ci "${w[i]#-D}" + hook::wrapper_chdir_record sudo_ci "${stok#-D}" ((i++)) ;; -u | -g | -h | -p | -C | -R | -T | --user | --group) ((i += 2)) ;; diff --git a/plugins/source-control/.claude-plugin/plugin.json b/plugins/source-control/.claude-plugin/plugin.json index 2623e3b537..966589cb71 100644 --- a/plugins/source-control/.claude-plugin/plugin.json +++ b/plugins/source-control/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json", "name": "source-control", - "version": "0.53.14", + "version": "0.53.15", "description": "Git and GitHub delivery workflow: /commit (Conventional Commits + Co-authored-by trailer via safe heredoc mechanics), /pull-request (prep, create, CI monitoring, review-comment triage, merge, CI-log fetch), /babysit-prs (self-pacing fleet loop \u2014 safe by default; opt-in worker/autopilot tiers add gate-checked merge and thread resolution behind a deterministic Python engine), /babysit-loop (the loop-lane merge lane: a standing or drain loop that invokes babysit-prs per cycle, configured through repo-scoped babysit_loop_* keys on the layered source-control.md seam, with merge authority human-only until the target repo's tracked config adopts the lane, a gate-proven C2-mechanical baseline once adopted, and standing merge-rung raises binding from the team-tracked layer only \u2014 with one named exception, where an invocation line explicitly typing both the autopilot tier keyword and the dedicated raise argument --merge c3-this-run widens that single invocation's merge authority up to C3 behind a fresh independent frontier-tier resolver, while C4-structural and C5-untrusted-provenance stay unconditionally human-merge), /worktree (create, status, cleanup, audit for parallel-session isolation), /setup (check the effective commit-subject / PR-title convention merged across its config layers and the babysit-prs config, or apply \u2014 interview the repo and write the convention config to a chosen layer), and /resolve-conflicts (intent-first merge/rebase conflict resolution with a semantic-conflict sweep \u2014 never --abort). The commit-subject / PR-title convention is configurable via a source-control.md config written by a re-runnable setup skill, layered across a ~/.claude user-global file, the tracked team file, and a gitignored .claude/source-control.local.md personal overlay merged per key; Conventional Commits is the default when no convention is declared.", "author": { "name": "Melodic Software", diff --git a/plugins/source-control/CHANGELOG.md b/plugins/source-control/CHANGELOG.md index 13866940b0..95eac053ea 100644 --- a/plugins/source-control/CHANGELOG.md +++ b/plugins/source-control/CHANGELOG.md @@ -3,6 +3,12 @@ All notable changes to the `source-control` plugin are documented here. Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); this plugin uses semantic versioning. +## [0.53.15] + +### Changed + +- **Synced `hook-utils.sh`:** peel sudo clustered short options for chdir resolution (#1811); widen the valueless-short peel set and keep `-h` value-taking. + ## [0.53.14] ### Changed diff --git a/plugins/source-control/hooks/hook-utils.sh b/plugins/source-control/hooks/hook-utils.sh index 0776e2f766..41a9b28420 100644 --- a/plugins/source-control/hooks/hook-utils.sh +++ b/plugins/source-control/hooks/hook-utils.sh @@ -1443,26 +1443,30 @@ hook::git_resolve_index() { ;; sudo) # sudo's own chdir is -D/--chdir (its -C is close-from, -R is --chroot). - # Only the unclustered spellings are read here; sudo's valueless short set - # is large and release-dependent, so peeling a cluster the way the env - # branch does would be guesswork rather than grammar. - # Known gap, fail-open: a clustered `sudo -bD dir git …` loses the chdir, - # and `-i` relocates to the target user's home without naming a directory - # at all. + # GNU sudo clusters short options, so `-bD dir` carries a chdir that no + # exact `-D` match sees. Peel the documented valueless shorts (-A/-B/-b/-e/-E + # -H/-K/-k/-l/-n/-P/-s/-S/-v/-V, per `sudo --help`) off a single-dash token + # so the value-taking tail (-D/--chdir, -u/-g/-h/-p/-C/-R/-T) reaches its own + # branch. `-h` is value-taking (`-h host` / `--host=`) and must not be peeled. + # `-i` relocates to the target user's home without naming a directory at all. ((i++)) - local sudo_ci=-1 + local sudo_ci=-1 stok while ((i < n)) && [[ "${w[i]}" == -* ]]; do - case "${w[i]}" in + stok="${w[i]}" + if [[ "$stok" == -[!-]* ]]; then + while [[ "$stok" =~ ^-[ABbeEHKklnPsSvV](.+)$ ]]; do stok="-${BASH_REMATCH[1]}"; done + fi + case "$stok" in -D | --chdir) ((i + 1 < n)) && hook::wrapper_chdir_record sudo_ci "${w[i + 1]}" ((i += 2)) ;; --chdir=*) - hook::wrapper_chdir_record sudo_ci "${w[i]#--chdir=}" + hook::wrapper_chdir_record sudo_ci "${stok#--chdir=}" ((i++)) ;; -D*) - hook::wrapper_chdir_record sudo_ci "${w[i]#-D}" + hook::wrapper_chdir_record sudo_ci "${stok#-D}" ((i++)) ;; -u | -g | -h | -p | -C | -R | -T | --user | --group) ((i += 2)) ;; diff --git a/plugins/typos-format/.claude-plugin/plugin.json b/plugins/typos-format/.claude-plugin/plugin.json index 78197f2cb1..e1073e51fc 100644 --- a/plugins/typos-format/.claude-plugin/plugin.json +++ b/plugins/typos-format/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json", "name": "typos-format", - "version": "0.6.8", + "version": "0.6.10", "description": "Spell-check on edit via typos-cli, unconditionally \u2014 report-only by default, honoring the consuming repo's own typos configuration when one is present.", "author": { "name": "Melodic Software", diff --git a/plugins/typos-format/CHANGELOG.md b/plugins/typos-format/CHANGELOG.md index 072a916947..1391df09e5 100644 --- a/plugins/typos-format/CHANGELOG.md +++ b/plugins/typos-format/CHANGELOG.md @@ -3,6 +3,18 @@ All notable changes to the `typos-format` plugin are documented here. Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); this plugin uses semantic versioning. +## [0.6.10] + +### Changed + +- **Synced `hook-utils.sh`:** peel sudo clustered short options for chdir resolution (#1811); widen the valueless-short peel set and keep `-h` value-taking. + +## [0.6.9] + +### Changed + +- **Synced `hook-utils.sh`:** peel sudo clustered short options for chdir resolution (#1811). + ## [0.6.8] ### Changed diff --git a/plugins/typos-format/hooks/hook-utils.sh b/plugins/typos-format/hooks/hook-utils.sh index 0776e2f766..41a9b28420 100644 --- a/plugins/typos-format/hooks/hook-utils.sh +++ b/plugins/typos-format/hooks/hook-utils.sh @@ -1443,26 +1443,30 @@ hook::git_resolve_index() { ;; sudo) # sudo's own chdir is -D/--chdir (its -C is close-from, -R is --chroot). - # Only the unclustered spellings are read here; sudo's valueless short set - # is large and release-dependent, so peeling a cluster the way the env - # branch does would be guesswork rather than grammar. - # Known gap, fail-open: a clustered `sudo -bD dir git …` loses the chdir, - # and `-i` relocates to the target user's home without naming a directory - # at all. + # GNU sudo clusters short options, so `-bD dir` carries a chdir that no + # exact `-D` match sees. Peel the documented valueless shorts (-A/-B/-b/-e/-E + # -H/-K/-k/-l/-n/-P/-s/-S/-v/-V, per `sudo --help`) off a single-dash token + # so the value-taking tail (-D/--chdir, -u/-g/-h/-p/-C/-R/-T) reaches its own + # branch. `-h` is value-taking (`-h host` / `--host=`) and must not be peeled. + # `-i` relocates to the target user's home without naming a directory at all. ((i++)) - local sudo_ci=-1 + local sudo_ci=-1 stok while ((i < n)) && [[ "${w[i]}" == -* ]]; do - case "${w[i]}" in + stok="${w[i]}" + if [[ "$stok" == -[!-]* ]]; then + while [[ "$stok" =~ ^-[ABbeEHKklnPsSvV](.+)$ ]]; do stok="-${BASH_REMATCH[1]}"; done + fi + case "$stok" in -D | --chdir) ((i + 1 < n)) && hook::wrapper_chdir_record sudo_ci "${w[i + 1]}" ((i += 2)) ;; --chdir=*) - hook::wrapper_chdir_record sudo_ci "${w[i]#--chdir=}" + hook::wrapper_chdir_record sudo_ci "${stok#--chdir=}" ((i++)) ;; -D*) - hook::wrapper_chdir_record sudo_ci "${w[i]#-D}" + hook::wrapper_chdir_record sudo_ci "${stok#-D}" ((i++)) ;; -u | -g | -h | -p | -C | -R | -T | --user | --group) ((i += 2)) ;;