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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 14 additions & 10 deletions lib/hook-utils.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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)) ;;
Comment thread
kyle-sexton marked this conversation as resolved.
Expand Down
4 changes: 4 additions & 0 deletions lib/hook-utils.test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion plugins/actionlint/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -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",
Expand Down
12 changes: 12 additions & 0 deletions plugins/actionlint/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
24 changes: 14 additions & 10 deletions plugins/actionlint/hooks/hook-utils.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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)) ;;
Expand Down
2 changes: 1 addition & 1 deletion plugins/autonomy/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -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",
Expand Down
6 changes: 6 additions & 0 deletions plugins/autonomy/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
24 changes: 14 additions & 10 deletions plugins/autonomy/hooks/hook-utils.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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)) ;;
Expand Down
2 changes: 1 addition & 1 deletion plugins/bash-format/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -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",
Expand Down
6 changes: 6 additions & 0 deletions plugins/bash-format/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
24 changes: 14 additions & 10 deletions plugins/bash-format/hooks/hook-utils.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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)) ;;
Expand Down
2 changes: 1 addition & 1 deletion plugins/biome-format/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -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",
Expand Down
6 changes: 6 additions & 0 deletions plugins/biome-format/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
24 changes: 14 additions & 10 deletions plugins/biome-format/hooks/hook-utils.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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)) ;;
Expand Down
2 changes: 1 addition & 1 deletion plugins/claude-ops/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -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",
Expand Down
12 changes: 12 additions & 0 deletions plugins/claude-ops/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading