25 Commits
Author SHA1 Message Date
nanaubusinessandAdmin 85cc1d9935 fix: copilot-plugin test checks all 6 command files (#393)
Previously only checked 4 of 6. ponytail-gain.toml and
ponytail-help.toml are now validated.

Closes #381

Co-authored-by: Admin <admin@Admins-MacBook-Pro.local>
2026-06-30 00:21:09 +02:00
Emeriko ac75159e5e Merge branch 'main' into salaamdev/main
# Conflicts:
#	README.md
2026-06-26 03:08:24 +02:00
b9fa564429 feat: inject ponytail ruleset into subagents via SubagentStart hook (#254)
* feat: inject ponytail ruleset into subagents via SubagentStart hook

SessionStart additionalContext is parent-thread only, so every Task-spawned
agent ran ponytail-unaware. Add a SubagentStart hook that injects the active
ruleset into each subagent, reusing getPonytailInstructions. Native Claude
needs the hookSpecificOutput JSON form (not raw stdout), so writeHookOutput
grows a SubagentStart branch; readMode exposes the live flag.

Workflow- and team-spawned coverage is undocumented upstream; verify in a
fresh session once installed.

Closes #252

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H1dMag33yz1Kf1jS24Aira

* fix: address QA round 1 — make hook tests hermetic + cover Codex SubagentStart

QA round 1 (panel + deepseek-v4-pro) found two real test issues:
- The new subagent block (and the pre-existing claudeEnv block) used a no-op
  `delete env.PLUGIN_DATA`; run() spreads process.env, so a PLUGIN_DATA /
  COPILOT_PLUGIN_DATA leaked from the shell would steer writeHookOutput into the
  codex/copilot branch and silently mis-fire the native-Claude assertions.
  Fixed at the source: neutralize both vars once at the top, like CLAUDE_CONFIG_DIR.
- The Codex SubagentStart branch (claude-codex-hooks.json is shared by both plugin
  manifests) had zero coverage. Added a codex-path assertion.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H1dMag33yz1Kf1jS24Aira

* fix: use PowerShell-safe command form for SubagentStart hook

Match the post-#265 'node ...; exit 0' form used by the sibling hooks. The old 'command -v node ... || exit 0' form fails tests/hooks-windows.test.js (POSIX-guard and non-blocking asserts) once this branch merges onto current main.

---------

Co-authored-by: Shane McCarron <shane.mccarron@corvexconnect.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Emeriko <dietrich.gebert@gmail.com>
2026-06-24 04:19:14 +02:00
Dang Trung AnandEmeriko 17a466013e feat: publish ponytail as an installable npm package for OpenCode and Pi (#197)
* feat: register slash commands from .opencode/command/*.md

Add parseCommandFile() to read frontmatter-described markdown files
and wire them into opencode's config.command during init.

Extend the config hook to scan .opencode/command/ and register each
.md file as a named slash command.

Update the plugin doc comment to reflect the npm install path
(opencode-ponytail) vs the old relative path.

* chore: rename package to opencode-ponytail

Align package name with npm convention for opencode plugins.
Update keywords to include opencode-plugin and opencode tags.
Fix description back to original correct wording (grammatical
regression introduced during editing).

* chore: add npm metadata and publish workflow

Add author, homepage, repository, bugs, main, exports, files, and
publishConfig fields to package.json for npm publishing.

Add .github/workflows/publish.yml to auto-publish to npm on version
tags (v*) with provenance.

* docs: add npm plugin install for opencode-ponytail

---------

Co-authored-by: Emeriko <dietrich.gebert@gmail.com>
2026-06-24 02:09:40 +02:00
Haoqian 2b426c6ac9 fix: make shared hooks parse in PowerShell (#265) 2026-06-24 01:42:40 +02:00
Isha katiyar ae24cd00bc fix: add uninstall cleanup script for state outside plugin files (#226) (#228) 2026-06-23 23:38:06 +02:00
DietrichGebert 215777d835 fix: don't embed shell-unsafe install paths in statusline setup nudge (#224)
The SessionStart nudge built a statusLine command by interpolating the
plugin's __dirname path into a double-quoted shell string. A clone path
containing shell metacharacters (quotes, &, $, backtick, ;) could break
out when the suggested command later runs via the statusline shell.

Low severity in practice: the path is the install location, so triggering
it requires installing into a maliciously-named directory, i.e. the
attacker already controls the filesystem. Hardening it anyway.

Gate the snippet behind isShellSafe() (allowlist of ordinary path chars,
allowing : \ / for normal Windows and POSIX paths). Unsafe paths fall
back to a manual-setup instruction instead of an embeddable command. An
allowlist beats a per-shell escaper, which is its own edge-case bug farm.

Refs #200
2026-06-21 01:58:21 +02:00
DietrichGebertandClaude Opus 4.8 248a30b40b test: simplify hooks temp-dir cleanup to a one-line exit handler (#221)
#213 guarded cleanup with a flag + named function + process.once. But
fs.rmSync with force:true already no-ops on a missing path, so the guard
and the explicit end-of-file call are unnecessary. Collapse to a single
process.on('exit') handler.

Refs #204

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 01:29:09 +02:00
Lixin2026 ee263e5708 test: clean hooks temp dir on failure (#213) 2026-06-21 01:20:45 +02:00
salaamdev 731d3193e7 Merge branch 'main' into main 2026-06-19 05:58:49 +03:00
Sonai Biswas 4dad14fac5 Avoid Gemini loading Claude hook events (#139) 2026-06-19 00:24:43 +02:00
Lakshya77089 53fd1e850e fix: only deactivate on a standalone "stop ponytail" / "normal mode" (#162)
The deactivation check matched the phrase anywhere in the prompt, so an
ordinary request like "add a normal mode toggle" silently turned ponytail
off for the rest of the session. Match the whole message instead (trimmed,
case-insensitive, trailing punctuation ignored) through a shared helper used
by both the Claude/Codex hook and the pi extension.

Fixes #161
2026-06-18 22:50:03 +02:00
salaamdev b4f725f7ce Merge branch 'main' into main 2026-06-18 10:45:26 +03:00
DietrichGebertandClaude Opus 4.8 41d6c2f761 feat: ship ponytail to OpenClaw (ClawHub skill package) (#102)
Adds .openclaw/skills/ (ponytail + review/audit/debt/help) generated from the canonical skills/ (verbatim body, no drift), a generator script, and a drift test. Verified live: loads as Ready in OpenClaw 2026.6.6.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 13:35:35 +02:00
Abdisalam Hassan 4198fc30ac add Hermes plugin for Ponytail with command support and documentation 2026-06-15 19:57:45 +00:00
YIZIHN 084f10fb48 fix: ship the missing /ponytail-help command on Claude Code and OpenCode (#62)
Ships the previously-missing /ponytail-help adapter files (commands/ponytail-help.toml, .opencode/command/ponytail-help.md) and adds tests/commands.test.js, a parity guard asserting every pi-registered command has both adapter files. Thanks @hooni0918.
2026-06-15 16:32:02 +02:00
c1c80f3cc8 Adding support for Copilot Marketplace plugin (#47)
* Add GitHub Copilot plugin and marketplace manifests for Ponytail

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add Copilot hook adapters and plugin data runtime precedence

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Document Copilot plugin install flow and instruction fallback mode

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix Copilot hooks for native output context and state-only mode tracking

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* docs: add Copilot CLI namespaced command examples

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Collapse Copilot hooks into shared activate/mode-tracker

The Copilot hook files duplicated ponytail-activate.js and
ponytail-mode-tracker.js, differing only in output shape. Move that
difference into writeHookOutput (isCopilot branch) and point
copilot-hooks.json at the shared hooks. Deletes both forks (-73 lines).

Refs #1

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Align Copilot manifest version to 4.4.0 with cross-manifest parity test

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Make Copilot and Codex host detection exclusive in runtime output routing

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add Copilot debt command validation with a pull request acceptance checklist

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Removed PR template

* Drop tautological copilot command-form test

The namespaced-form assertion built '/ponytail:ponytail-debt' from two
constants and compared it to itself — it tests string concatenation, not
wiring. The file-exists check above already catches a renamed manifest.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 11:02:59 +02:00
DietrichGebertandClaude Opus 4.8 f3da910b4f feat: refine ruleset from a full-project field review (#39)
* feat: refine ruleset from a full-project field review

A reviewer ran ponytail across a 9-phase rewrite (protocol, PC app, simulator,
RPi daemon, ESP32 firmware) and flagged three gaps. All three land in SKILL.md
and propagate to AGENTS.md + the rule copies:

- Promote the one-runnable-check rule to a headline ("Lazy code without its
  check is unfinished"), enforced as a check-rule-copies invariant.
- Hardware carve-out in "When NOT to be lazy": a real device is never the spec
  ideal (clock drift, sensor offset), leave the calibration knob.
- Clarify the Output rule: explanation the user explicitly asked for is not
  debt, only unrequested prose is.

Fallback instructions kept in sync. Rule-copy check + tests green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* test: add a behavior gate proving the refinements actually fire

The refinements were verified as injected text, but injected != behavioral.
This adds a behavior eval that probes each refined rule on a task that should
trigger it:

- hardware    -> does the output leave a calibration knob?
- explanation -> when a write-up is explicitly requested, is it given in full?
- onecheck    -> is a runnable check left behind?

benchmarks/behavior.yaml runs the probes (baseline vs ponytail arm); the
grader benchmarks/behavior.js is proven by tests/behavior.test.js (8 cases,
RED/GREEN, no API key, runs in CI). Live-confirmed: the model under the
current ruleset passes all three gates, graded by the same grader.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 02:02:50 +02:00
DietrichGebertandClaude Opus 4.8 01578c0cd4 fix: honor CLAUDE_CONFIG_DIR in hooks (#37)
ponytail-activate.js and ponytail-runtime.js hardcoded ~/.claude for the
flag file and settings lookup, ignoring CLAUDE_CONFIG_DIR. Add a shared
getClaudeDir() to ponytail-config.js and use it in both. Regression test
added to hooks.test.js.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 00:00:01 +02:00
at384 6d990f8c54 feat(benchmarks): add correctness assertion (#31)
* feat(benchmarks): add correctness assertion - proves less code is not broken code

The existing benchmark measures lines-of-code (loc.js) but never checks
whether the generated code actually works. This adds a functional
correctness gate (correctness.js) that extracts code from fenced blocks
and runs per-task checks:

- email validator: spawns Python, asserts accept/reject on 5 inputs
- debounce: spawns Node, asserts delayed execution + reset on re-call
- csv sum: spawns Python with a test CSV, asserts correct total (351)
- countdown (React): structural check (useState + useEffect + decrement)
- rate limiter (FastAPI): structural check (limit logic + framework usage)

12 unit tests (node:test) cover good/bad outputs for every task plus the
unknown-task edge case. Existing tests and rule-copy checks unaffected.

* fix: address review feedback

- csv check: use regex lookaround instead of substring match to prevent
  false positives (e.g. 13510 containing '351')
- ratelimit: fix operator precedence in block finder by adding parens
  around the || inside the !b.lang guard
- README: note that React/FastAPI checks are structural only, add
  prerequisites section (Python 3, pandas, Node.js 18+)
- test: add regression test for csv substring false positive
2026-06-14 23:42:01 +02:00
Ben YounesandClaude Opus 4.8 e01aa900f7 feat: add Gemini CLI support (#25)
* feat: add Gemini CLI support

Add a thin Gemini CLI extension adapter (closes #22). The manifest points
contextFileName at the existing AGENTS.md for always-on rules and reuses the
repo's commands/*.toml (/ponytail, /ponytail-review) and skills/, which Gemini
CLI auto-discovers — no rule text is duplicated.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* test: read manifest inside cases for a clean RED

The manifest was parsed at module scope, so reverting the adapter crashed the
whole test file at load (ENOENT) and collapsed all four cases into one
unreadable failure. Read it inside each case via a helper that asserts existence
first, so a missing or malformed manifest surfaces as clear per-case assertion
failures instead of a stack trace.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-14 17:50:02 +02:00
Ben YounesandClaude Opus 4.8 147bcfd621 fix: use PowerShell $env: syntax for Windows hook paths (#26)
On Windows the lifecycle hooks run via PowerShell, which does not expand
cmd.exe-style %CLAUDE_PLUGIN_ROOT%. The path was passed literally, so the hook
launcher could not find the script and both SessionStart and UserPromptSubmit
failed with exit code 1 (issue #19). Switch the two commandWindows entries to
$env:CLAUDE_PLUGIN_ROOT, keeping the working node + .js invocation.

Add a regression test that rejects cmd.exe %VAR% syntax in commandWindows and
asserts every hook command points at a script that actually ships in hooks/.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-14 17:39:59 +02:00
DietrichGebert 46c5c28b35 feat: add OpenCode adapter
Thin OpenCode plugin injecting the ponytail ruleset via experimental.chat.system.transform, reusing the shared instruction builder. Verified end-to-end on OpenCode 1.17.4. Supersedes #15.
2026-06-13 03:20:44 +02:00
dgebertandClaude Opus 4.8 515fb4c5a4 fix: make hook compatibility test cross-platform (USERPROFILE for Windows os.homedir)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-12 17:11:05 +02:00
Paul c16f967d37 feat: codex support 2026-06-12 08:49:33 -04:00