Merge branch 'main' into main

This commit is contained in:
salaamdev
2026-06-19 05:58:49 +03:00
committed by GitHub
64 changed files with 3119 additions and 64 deletions
+12
View File
@@ -25,6 +25,10 @@ const VERSIONED_MANIFESTS = [
// Gemini auto-discovers these by directory; the manifest is only useful if they exist.
const REUSED_COMMANDS = ['commands/ponytail.toml', 'commands/ponytail-review.toml'];
const REUSED_SKILLS = ['skills/ponytail/SKILL.md'];
// Gemini CLI auto-loads this exact path for extension hooks. Ponytail's
// Claude/Codex hook map uses events Gemini does not support, so it must stay
// behind the host-specific plugin manifests instead.
const GEMINI_AUTO_HOOKS = 'hooks/hooks.json';
// Same load-bearing phrases asserted by scripts/check-rule-copies.js: the file
// contextFileName points at must actually carry the rules, not just exist.
const RULE_INVARIANTS = [
@@ -77,3 +81,11 @@ test('the commands and skills the adapter reuses are present', () => {
assert.ok(fs.existsSync(path.join(root, rel)), `reused file missing: ${rel}`);
}
});
test('Gemini cannot auto-discover Claude/Codex hook events', () => {
assert.equal(
fs.existsSync(path.join(root, GEMINI_AUTO_HOOKS)),
false,
`${GEMINI_AUTO_HOOKS} is auto-loaded by Gemini CLI; keep Claude/Codex hooks on manifest paths`,
);
});
+12 -1
View File
@@ -11,7 +11,11 @@ const fs = require('fs');
const path = require('path');
const root = path.join(__dirname, '..');
const HOOKS_JSON = 'hooks/hooks.json';
const HOOKS_JSON = 'hooks/claude-codex-hooks.json';
const HOST_PLUGIN_MANIFESTS = [
'.claude-plugin/plugin.json',
'.codex-plugin/plugin.json',
];
// cmd.exe variable syntax (%FOO%); PowerShell leaves it literal, breaking the path.
const CMD_VAR_SYNTAX = /%[A-Za-z_][A-Za-z0-9_]*%/;
// Pull the hooks/<script> a command launches, so we can check it exists.
@@ -46,3 +50,10 @@ test('every hook command points at a script that ships in hooks/', () => {
}
}
});
test('Claude and Codex manifests point at the shared host-specific hook config', () => {
for (const rel of HOST_PLUGIN_MANIFESTS) {
const manifest = JSON.parse(fs.readFileSync(path.join(root, rel), 'utf8'));
assert.equal(manifest.hooks, `./${HOOKS_JSON}`, `${rel} must not rely on root hooks auto-discovery`);
}
});
+17
View File
@@ -64,6 +64,23 @@ assert.equal(fs.existsSync(codexState), false);
output = JSON.parse(result.stdout);
assert.equal(output.systemMessage, 'PONYTAIL:OFF');
// A request that merely mentions "normal mode" must not deactivate ponytail.
result = run('ponytail-mode-tracker.js', codexEnv, JSON.stringify({ prompt: '@ponytail lite' }));
assert.equal(result.status, 0, result.stderr);
assert.equal(fs.readFileSync(codexState, 'utf8'), 'lite');
result = run(
'ponytail-mode-tracker.js',
codexEnv,
JSON.stringify({ prompt: 'add a normal mode toggle next to dark mode' }),
);
assert.equal(result.status, 0, result.stderr);
assert.equal(
fs.readFileSync(codexState, 'utf8'),
'lite',
'incidental "normal mode" in a request must not turn ponytail off',
);
const claudeEnv = {
HOME: home,
USERPROFILE: home,