Skip to content

Commit 17780b1

Browse files
committed
fix(qoder): keep the ruleset on the /ponytail default turn (#1114)
1 parent 2961b52 commit 17780b1

2 files changed

Lines changed: 26 additions & 4 deletions

File tree

‎hooks/ponytail-mode-tracker.js‎

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ function finish() {
4242
// Match /ponytail commands
4343
let modeSwitched = false;
4444
let deactivated = false;
45+
let defaultNotice = '';
4546
if (/^[/@$]ponytail/.test(prompt)) {
4647
const parts = prompt.split(/\s+/);
4748
const cmd = parts[0].replace(/^[@$]/, '/');
@@ -62,9 +63,12 @@ function finish() {
6263
const dmode = parts[2];
6364
if (dmode === 'off' || dmode === 'lite' || dmode === 'full' || dmode === 'ultra') {
6465
writeDefaultMode(dmode);
65-
writeHookOutput('UserPromptSubmit', dmode, 'PONYTAIL DEFAULT SET — new sessions start in ' + dmode + '.');
66+
defaultNotice = 'PONYTAIL DEFAULT SET — new sessions start in ' + dmode + '.';
67+
if (!isQoder) writeHookOutput('UserPromptSubmit', dmode, defaultNotice);
6668
}
67-
return; // don't fall through to the session-mode switch
69+
// Qoder still needs this turn's ruleset: the block below folds the
70+
// notice into it. mode stays null, so the session level is untouched.
71+
if (!isQoder) return; // don't fall through to the session-mode switch
6872
}
6973
if (arg === 'lite') mode = 'lite';
7074
else if (arg === 'full') mode = 'full';
@@ -146,10 +150,12 @@ function finish() {
146150
if (currentMode && currentMode !== 'off') {
147151
// ponytail: one JSON per invocation — mode-switch confirmation is
148152
// folded into the ruleset header so Qoder gets both in one write.
149-
const header = modeSwitched
153+
const header = (defaultNotice ? defaultNotice + '\n\n' : '') + (modeSwitched
150154
? 'PONYTAIL MODE CHANGED — level: ' + currentMode + '\n\n'
151-
: '';
155+
: '');
152156
writeHookOutput('UserPromptSubmit', currentMode, header + getPonytailInstructions(currentMode));
157+
} else if (defaultNotice) {
158+
writeHookOutput('UserPromptSubmit', currentMode, defaultNotice);
153159
}
154160
}
155161
} catch (e) {

‎tests/hooks.test.js‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -636,6 +636,16 @@ assert.match(
636636
/PONYTAIL MODE CHANGED — level: ultra/,
637637
);
638638

639+
// `/ponytail default lite` on Qoder: the turn still gets the live ruleset, with
640+
// the confirmation folded into the same JSON, and the live level stays ultra.
641+
const qoderDefaultEnv = { ...qoderEnv, XDG_CONFIG_HOME: path.join(qoderHome, '.config') };
642+
result = run('ponytail-mode-tracker.js', qoderDefaultEnv, JSON.stringify({ prompt: '/ponytail default lite' }));
643+
assert.equal(result.status, 0, result.stderr);
644+
assert.equal(fs.readFileSync(qoderState, 'utf8'), 'ultra');
645+
output = JSON.parse(result.stdout);
646+
assert.match(output.hookSpecificOutput.additionalContext, /^PONYTAIL DEFAULT SET — new sessions start in lite\./);
647+
assert.match(output.hookSpecificOutput.additionalContext, /PONYTAIL MODE ACTIVE — level: ultra/);
648+
639649
// "stop ponytail": deactivates and persists off so a later prompt does
640650
// not mistake the missing flag for first-run initialization.
641651
result = run(
@@ -657,6 +667,12 @@ assert.equal(result.status, 0, result.stderr);
657667
assert.equal(result.stdout, '', 'Qoder must stay off on later prompts');
658668
assert.equal(fs.readFileSync(qoderState, 'utf8'), 'off');
659669

670+
// While off, `/ponytail default` only confirms; it must not switch ponytail on.
671+
result = run('ponytail-mode-tracker.js', qoderDefaultEnv, JSON.stringify({ prompt: '/ponytail default full' }));
672+
assert.equal(result.status, 0, result.stderr);
673+
assert.equal(JSON.parse(result.stdout).hookSpecificOutput.additionalContext, 'PONYTAIL DEFAULT SET — new sessions start in full.');
674+
assert.equal(fs.readFileSync(qoderState, 'utf8'), 'off');
675+
660676
// Subagent injection via PreToolUse (task|Task matcher): when ponytail is
661677
// active, the subagent hook injects the ruleset. Qoder shares the same
662678
// ponytail-subagent.js script; the isQoder branch outputs hookSpecificOutput

0 commit comments

Comments
 (0)