feat(claude): nudge fresh sessions to load the pql + clide skills (T-490)

A fresh Claude session now gets a one-line preamble (clideSkillsNote) telling it
to reach for the bundled pql + clide skills from its first turn rather than
rediscovering the workflows. Layered onto clideContextNote in the single
--append-system-prompt.

Gated on a NEW session (!spec.resume && !spec.isFork): new tabs and the
post-/clear respawn spawn with resume:false and get it; the account-change
respawn (T-480) and real resumes carry prior context (resume:true), and forks
inherit their source — none are re-nagged. Both skills already ship (pql
user-scope, clide repo-scope), so no precursor was needed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-28 10:53:08 +02:00
co-authored by Claude Opus 4.8
parent a46677facf
commit 84f4b20cb8
7 changed files with 108 additions and 0 deletions
@@ -28,6 +28,17 @@ void main() {
});
});
group('clideSkillsNote (T-490)', () {
test('names both skills, nudges first-turn use, and stays short', () {
final note = clideSkillsNote();
expect(note, contains('`pql`'));
expect(note, contains('`clide`'));
expect(note, contains('from your first turn'));
// Acceptance #4: a short nudge, not a wall of text crowding clideContextNote.
expect(note.length, lessThan(360));
});
});
group('clideBashAllowRule (T-217)', () {
test('is the command-scoped Bash rule and rides on --allowedTools', () {
expect(clideBashAllowRule, 'Bash(clide:*)');
@@ -53,6 +53,22 @@ void main() {
expect(spawnedArgs.single, isNot(contains('--effort')));
});
test('a fresh session gets the skills nudge; resume + fork do not (T-490)', () async {
String appendPrompt(List<String> args) {
final i = args.indexOf('--append-system-prompt');
return i >= 0 ? args[i + 1] : '';
}
await orch.spawn(spec('primary')); // fresh (resume:false)
expect(appendPrompt(spawnedArgs.single), contains('from your first turn'), reason: 'fresh session is nudged');
await orch.spawn(SpawnSpec(id: 'resumed', role: 'r', sessionId: 'r-uuid', cwd: '/repo', resume: true));
expect(appendPrompt(spawnedArgs.last), isNot(contains('from your first turn')), reason: 'resume carries context');
await orch.spawn(SpawnSpec(id: 'fork', role: 'f', sessionId: 'f-uuid', cwd: '/repo', forkSourceSessionId: 'primary-uuid'));
expect(appendPrompt(spawnedArgs.last), isNot(contains('from your first turn')), reason: 'fork inherits its source');
});
test('spawns multiple concurrent sessions, each with its own process', () async {
await orch.spawn(spec('primary'));
await orch.spawn(spec('teammate:tyre'));