Commit Graph
5 Commits
Author SHA1 Message Date
rUvandReuven f0ee0f9688 fix(#1921): plugin hooks use a resilient shim, not bare npx @alpha per fire (#1923)
* fix(#1921): plugin hooks invoke a resilient shim, not bare `npx @alpha` per fire

Every PreToolUse/PostToolUse/Stop hook ran `npx <pkg>@alpha hooks …`, which
(a) re-resolves the @alpha dist-tag from the registry on every fire and
(b) re-installs from cold cache — and when that install crashes (an arborist
`Invalid Version` on npm 10.8.x, deep in a transitive OTEL/grpc subtree) the
user sees a hook error in Claude Code after every assistant turn, plus ~7s of
wasted registry traffic per turn.

Fix: each plugin (`.claude-plugin/`, `plugin/`, `plugins/ruflo-core/`) ships
`scripts/ruflo-hook.sh` — prefers an already-installed `ruflo`/`claude-flow`
binary, falls back to `npx --prefer-offline --yes ruflo@alpha`, and ALWAYS
exits 0. hooks.json invokes `"${CLAUDE_PLUGIN_ROOT}/scripts/ruflo-hook.sh" …
|| true` (the `|| true` covers the unset-$CLAUDE_PLUGIN_ROOT case). stdin
(the hook event JSON) passes through unchanged; the stdin-jq-xargs
shell-injection-safety pattern in plugin/hooks/hooks.json is preserved.

This does NOT fix the underlying arborist crash (which needs the offending
empty-`version` package pinned via `overrides` once it's identified on
npm 10.8.2 — see the issue thread) — it makes a CLI/install failure invisible
and cheap instead of a visible error every turn.

CI guard: scripts/audit-hook-commands.mjs — fails CI if any hook `command`
uses `npx` without `--prefer-offline`, or invokes the CLI without a non-fatal
guard. Wired into v3-ci.yml as `hook-command-audit` (also bash-lints each
ruflo-hook.sh and asserts it exits 0 with no CLI on PATH) + added to
witness-verify needs[]. Path triggers updated to fire on `**/hooks/hooks.json`,
`**/scripts/ruflo-hook.sh`, and `scripts/**`. Witness markers for #1921 +

Co-Authored-By: RuFlo <ruv@ruv.net>

* fix(#1921): make test-hooks.mjs shim-aware; fix shim-lint CI step; regen witness

Rebasing #1921 onto main surfaced 3 CI failures:

- plugin-hooks-smoke (ubuntu + macos): test-hooks.mjs substituted only
  `npx ruflo@alpha` → the local CLI, but the hooks.json now invokes
  `${CLAUDE_PLUGIN_ROOT}/scripts/ruflo-hook.sh <args>`. It now also
  substitutes the shim path → `<cli> hooks <args>` (bypassing the shim, so
  the test exercises the real CLI flag wiring) and strips the shim's
  trailing `|| true` so exit codes are still asserted. 7/7 pass.
- hook-command-audit shim-lint step: `PATH="/nonexistent" bash "$sh"` set
  PATH to a dir with no `bash`, so `bash: command not found`. Now invokes
  bash by full path with `PATH=` empty: `PATH= "$BASH" "$sh"` — the shim's
  `command -v` is a builtin (works with empty PATH) and the npx fallback
  fails cleanly under `|| true` → exit 0. (resolved in v3-ci.yml during the
  rebase.)

Witness manifest regenerated; #1862's marker refreshed to match the
shim-relocated `post-edit -f "$FILE" -s true` (the documented-flag form is
preserved). `ruflo verify` 0 regressed.

Co-Authored-By: RuFlo <ruv@ruv.net>

---------

Co-authored-by: Reuven <cohen@ruv-mac-mini.local>
2026-05-12 00:51:18 -04:00
ReuvenandRuFlo 004dda36dd fix(plugin): repoint plugin/agents symlink at .claude/agents (33 active md files)
The repo-as-Claude-Code-plugin manifest at plugin/.claude-plugin/plugin.json
declares "agents": "./agents", but the symlink at plugin/agents pointed
at ../v2/.claude/agents — a path that never existed at repo root and
was definitively gone after archive/v2/ moves. Result: anyone installing
this repo via /plugin got zero agents loaded.

Repointed to ../.claude/agents (33 active md files: coder, reviewer,
tester, planner, researcher, security-architect, etc). The hooks /
commands / skills symlinks were already correct.

Verified: ls -L plugin/agents resolves to 33 entries; matches what
.claude/agents/ contains.

Co-Authored-By: RuFlo <ruv@ruv.net>
2026-05-06 11:12:35 -04:00
rUvandReuven d5fbb3bc4e fix(hooks): stop creating empty files via $TOOL_INPUT shell injection (#1747) (#1757)
The Liberation of Bajor team's report (#1747) is a precise diagnosis:
\`plugin/hooks/hooks.json\` interpolated \`\$TOOL_INPUT_command\` (and
\`\$TOOL_INPUT_*\`, \`\$PROMPT\`, \`\$TOOL_NAME\` etc.) directly into
double-quoted command strings. When the bash command being executed
contained both \" and >, the wrapping quotes broke and the shell
re-parsed the inner content. Any > became a redirect, creating empty
files at CWD with names like '3', '40)', 'maxWidth)', etc.

After ~24h of normal usage on Windows + Git Bash, dozens of empty
files accumulated at every project root.

Fix: rewrite ALL 13 command hooks to use the stdin-jq-xargs pattern
that the companion file \`.claude-plugin/hooks/hooks.json\` already
uses safely:

    cat | jq -r '.tool_input.command // empty' | tr '\\\\n' '\\\\0' \\
        | xargs -0 -I {} npx claude-flow@alpha hooks pre-command --command '{}'

Reading via stdin + jq + xargs -0 -I {} bypasses shell re-parsing
entirely. The user input becomes a single argv element, never
re-interpreted as shell tokens.

Validation (script in commit):
  safe (stdin-jq): 13   unsafe (\$-interp): 0

Affected hooks (all rewritten):
  PreToolUse:  Bash, Write|Edit|MultiEdit, Task, Grep|Glob|Read,
               mcp__claude-flow__*
  PostToolUse: same 5 matchers
  UserPromptSubmit: route by .prompt
  SessionStart:    by .session_id
  Notification:    by .message

Dropped non-essential \$TOOL_SUCCESS / \$TOOL_EXIT_CODE flags from
post-* hooks — they're internal booleans/numbers (not user input,
so not the file-creation vector) but the cleaner stdin-only pattern
is preferable over mixed inline/stdin.

Stop / SubagentStop / PermissionRequest hooks unchanged — they don't
interpolate user input.

This is a plugin-file change; no npm publish needed. The fix is live
when the PR merges and users pull main / re-clone.

Closes #1747.

Co-authored-by: Reuven <cohen@ruv-mac-mini.local>
2026-05-05 10:43:52 -04:00
rUv 282143a60d Fix init hook bugs: TOOL_INPUT_prompt overflow and description field (#1161)
The PreToolUse:Task hook used $TOOL_INPUT_prompt which expands to the
full agent prompt (thousands of characters), overflowing the shell's
argument length limit. Switched to $TOOL_INPUT_description (the short
3-5 word field) and truncated to 200 chars.

Fixes #1160
2026-02-17 13:28:48 -08:00
rUvandClaude Sonnet 4 a1332c0935 checkpoint: File edit:
🚀 Generated with [Claude Code](https://claude.com/claude-code)
📊 V3 Development Progress Checkpoint

Co-Authored-By: Claude Sonnet 4 <noreply@anthropic.com>
2026-01-05 19:30:53 +00:00