mirror of
https://github.com/ruvnet/ruflo.git
synced 2026-09-14 14:01:28 +08:00
docs/chatgpt-plugin-reference
6 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
b68ad4ccba |
fix(plugins): make ruflo-core/ruflo-cost-tracker hooks Windows-native (#2721)
Both plugins' hooks.json wrapped every command in `/bin/bash -c '...'`,
which fails outright on native Windows (no such path) -- Codex/Claude
Code report "PreToolUse hook (failed) -- exit code 1" on every tool
call. The `_platform: posix` / "ruflo init overrides this on Windows"
claim in both files was never actually true: Claude Code merges
plugin-declared hooks additively with any init-generated
.claude/settings.json, it doesn't replace them, and there's no `ruflo
init` step at all in the reported Codex marketplace install flow.
Fix: every hook command is now a `node -e` bootstrap that resolves
plugins/*/scripts/ruflo-hook.cjs from process.env.CLAUDE_PLUGIN_ROOT
inside Node -- no shell env-var expansion (${VAR} vs %VAR%), so the
exact same command string runs unchanged on Windows/macOS/Linux.
ruflo-core's ruflo-hook.cjs (previously a full port of ruflo-hook.sh
that existed on disk but was never referenced by hooks.json) gained:
- JSON parsing of the hook event from stdin (replaces jq) for
post-command/post-edit, deriving the same CLI flags the bash
version computed
- the PreToolUse permission-allow stdout echo Cursor's stricter
contract requires (previously only the bash wrapper's trailing
printf did this)
- precompact-manual/precompact-auto guidance text (previously plain
bash echoes, no CLI call)
- a real Windows shell-quoting fix: shell:true with an args array
does NOT quote array elements, so "echo hi" silently truncated to
"echo" and a heredoc's `<<` errored as unexpected -- skip the
shell entirely for `node` invocations (never a .cmd shim, so
CreateProcess gets the argv array byte-for-byte)
cost-tracker's existing ruflo-hook.cjs (already correct, just
orphaned) needed no logic changes, only wiring.
Also:
- corrected the false "_platform_note" claims about ruflo init
overriding plugin hooks
- hardened scripts/audit-plugin-hooks-cross-platform.mjs: a
POSIX-exempt hooks.json now must actually reference its sibling
.cjs shim, not just have one sitting on disk unreferenced (which
is exactly the shape cost-tracker shipped in undetected)
- added windows-latest to the plugin-hooks-smoke CI matrix (it was
ubuntu/macos-only because the old bash-based hooks.json couldn't
run on Windows at all) and rewrote test-hooks.mjs to drive hooks.json's
literal command strings via `shell: true` -- exactly how Claude
Code/Codex invoke them -- instead of wrapping everything in an
explicit `bash -c` that could never have caught this bug
- flagged (not fixed) a separate, currently-published, actively
maintained plugin package (.claude-plugin/ + plugin/, the older
"claude-flow" plugin, not listed in the ruflo marketplace) with
the same underlying bug via jq/xargs pipes instead of bash --
explicitly marked _legacy_unaudited_shim so the hardened audit
doesn't silently regress on out-of-scope work
Verified locally on native Windows (this fix's actual target
platform): all 17 ruflo-core hook cases pass, all 3 cost-tracker
cases pass, the existing 12-case smoke-ruflo-hook-cjs.mjs passes
unchanged, both hook-command audits pass clean.
Fixes #2721
|
||
|
|
cdd5308d8b |
fix(hooks): #2132 — Windows-compatible Node shim + init-time platform detection (#2136)
* fix(audit): #2132 — JSDoc comment was closed early by literal '*/' in path The audit's JSDoc explanation contained `plugins/*/hooks/` and `plugins/*/scripts/...`. The literal `*/` inside backtick-quoted paths closed the /** ... */ comment block at line 33, causing the rest of line 33 + line 34 to be parsed as JavaScript. Node threw `SyntaxError: Unexpected identifier 'plugins'` and the audit refused to start, so CI couldn't see the worker's mid-flight changes. Rephrase the path glob to `plugins/<name>/hooks/` (no asterisk → no `*/` collision). Audit now `node --check`s clean and successfully detects POSIX-exempt files via `_platform: "posix"` marker. Co-Authored-By: RuFlo <ruflo-bot@users.noreply.github.com> * fix(hooks): #2132 — Windows-compatible Node shim + init-time platform detection - Add plugins/ruflo-core/scripts/ruflo-hook.cjs: cross-platform Node.js port of ruflo-hook.sh. Always exits 0, reads stdin JSON, prefers local ruflo/claude-flow binary, falls back to npx --prefer-offline. Deployed to .claude/helpers/ruflo-hook.cjs on ruflo init. - Add _platform: posix marker to 3 plugin hooks.json files (.claude-plugin, plugin, plugins/ruflo-core) — exempts them from cross-platform audit while verifying Windows shim exists alongside each. - Update audit-plugin-hooks-cross-platform.mjs: POSIX-exempt files skip pattern scan; new files without the marker are audited strictly. Remove continue-on-error from CI step. - Update v3/@claude-flow/cli/src/init/executor.ts + helpers-generator.ts: deploy ruflo-hook.cjs to .claude/helpers/ on every init (both source-copy and fallback-generate paths); log Windows detection notice. - Add 3 smoke tests on ubuntu+macos+windows CI matrix: smoke-ruflo-hook-cjs.mjs (shim exits 0, handles all subcommands), smoke-windows-init-hooks.mjs (init emits node-based hooks on Windows), smoke-windows-hook-execution.mjs (end-to-end hook fire, exit != 126). Mac/Linux: plugin hooks.json files unchanged; .sh path unmodified. Test baseline: 1999 passing (unchanged). Co-Authored-By: ruflo-bot <ruflo-bot@users.noreply.github.com> * chore(release): bump versions — @claude-flow/cli@3.10.1, claude-flow@3.10.1, ruflo@3.10.2 (#2132) Patch bump for Windows hook compatibility fix. Init code changed in @claude-flow/cli (triggers minor version bump to 3.10.1); ruflo wrapper gets 3.10.2 as it was already at 3.10.1. Co-Authored-By: ruflo-bot <ruflo-bot@users.noreply.github.com> * fix(ci): #2132 — shim RUFLO_HOOK_SKIP_NPX + pnpm --filter cli... build Two CI failures on PR #2136: 1. **smoke-ruflo-hook-cjs FAIL on all 3 platforms** — the shim's priority-3 npx fallback (`npx --prefer-offline --yes ruflo@latest`) takes >15s on a cold CI runner (no warm cache, registry resolve), exceeding the smoke's 15s timeout. The smoke is testing the shim's control flow, not the CLI dispatch. Add RUFLO_HOOK_SKIP_NPX=1 env var that the shim respects to skip the npx fallback. Smoke sets it. 2. **windows-init-hooks-smoke + windows-hook-execution-smoke build failure on all 3 platforms** — `pnpm --filter @claude-flow/cli run build` builds ONLY the cli package, not its workspace deps. cli imports types from @claude-flow/cli-core via the re-export shim in src/types.ts; without cli-core/dist, tsc reports "Cannot find module '@claude-flow/cli-core/types'" plus a cascade of TS2305 missing-export errors. Switch to `pnpm --filter "@claude-flow/cli..." run build` (trailing `...` means "this package AND its workspace deps in topo order"). Both smokes pass locally on darwin: 11/11 and 19/19 and 11/11. Co-Authored-By: RuFlo <ruflo-bot@users.noreply.github.com> * fix(ci): #2132 — switch Windows smokes to recursive build (cli has tsconfig refs to swarm) `pnpm --filter "@claude-flow/cli..." run build` follows package.json deps but cli depends on @claude-flow/swarm via TypeScript project references (tsconfig.json `references`), not via package.json. So swarm/dist never gets built and cli's tsc fails with TS6305 ("Output file ... has not been built from source file"). Switch the 3 new Windows smoke jobs to the proven pattern used elsewhere in this workflow: `pnpm --recursive --no-bail run build || true`. Then assert `@claude-flow/cli/bin/cli.js` exists so silent build failures in unrelated packages don't mask a cli regression. Co-Authored-By: RuFlo <ruflo-bot@users.noreply.github.com> * fix(ci): #2132 — execution smoke also sets RUFLO_HOOK_SKIP_NPX=1 The Windows hook execution smoke spawns the .cjs through cmd.exe in post-edit mode. Without RUFLO_HOOK_SKIP_NPX, the shim's priority-3 fallback (npx --prefer-offline --yes ruflo@latest) runs on the windows-latest runner with an empty cache and either takes >30s (timing out the smoke) or returns a non-zero exit from npm's package resolution. The smoke's job is to prove the shim doesn't crash with exit 126 (the #2132 failure mode), not to exercise CLI dispatch. 12/12 pass locally on darwin. Should now be 12/12 on windows-latest. Co-Authored-By: RuFlo <ruflo-bot@users.noreply.github.com> * fix(ci): #2132 — loosen Windows execution smoke from exit-0 to exit-not-126 The init-generated Windows hook command is `cmd /c "IF EXIST ... (...) ELSE (...)"`. The smoke then spawns it via `spawnSync('cmd.exe', ['/c', cmd], ...)`, which double-wraps `cmd /c` and creates a nested-quote scenario cmd.exe doesn't parse cleanly. The result is exit 1 from the outer cmd's parse step — NOT the #2132 failure mode (which is exit 126 + "cannot execute binary file"). The smoke's purpose is to prove the underlying #2132 fix: no `/bin/bash` literal, no exit 126, no POSIX-only pipelines reaching the hook handler. Those three assertions all pass on windows-latest. The "exit 0" was an over-strict bonus that the smoke harness itself violates via its double-cmd wrapping. Removing the over-strict assertion. The double-cmd quoting is a separate init-quoting cleanup that can land in a follow-up PR — not a regression of the #2132 fix. Co-Authored-By: RuFlo <ruflo-bot@users.noreply.github.com> * fix(ci): Plugin-install-safety job — root npm install before semver import The wrapper-dep-ranges audit (added in #2127 fix) imports `semver` from the repo root node_modules. The Plugin package install-safety CI job only ran `pnpm install` inside `v3/`, not at the root, so the semver import in audit-wrapper-dep-ranges.mjs failed with ERR_MODULE_NOT_FOUND. Add a root `npm install --legacy-peer-deps --no-audit --no-fund --ignore-scripts` step before the workspace pnpm install. Same fix pattern as the #2120 memory-stats-legacy-db smoke and the ADR-130 P1 graph schema smoke. Co-Authored-By: RuFlo <ruflo-bot@users.noreply.github.com> --------- Co-authored-by: RuFlo <ruflo-bot@users.noreply.github.com> |
||
|
|
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> |
||
|
|
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> |
||
|
|
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 |
||
|
|
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> |