From 9dfd3d1853ec492604d0943828dd6586b177d115 Mon Sep 17 00:00:00 2001 From: Dean Sharon Date: Sun, 22 Mar 2026 14:17:25 +0200 Subject: [PATCH] fix(ambient): ensure skill tool invocations happen before text output Skills were not loading despite correct classification because the model would print "Loading: X, Y" then skip the actual Skill tool calls. Fix by reversing the instruction order: invoke Skill tools first, then state classification text. This prevents the model from generating prose that overrides the tool-call requirement. --- CHANGELOG.md | 3 +++ scripts/hooks/ambient-prompt | 2 +- shared/skills/ambient-router/SKILL.md | 8 +++++--- tests/ambient.test.ts | 2 +- tests/integration/helpers.ts | 2 +- 5 files changed, 11 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dfd0dee..bceda1a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Fixed +- **Ambient mode**: skills not loading despite correct classification — reordered instructions so Skill tool invocations happen before any text output + --- ## [1.8.1] - 2026-03-22 diff --git a/scripts/hooks/ambient-prompt b/scripts/hooks/ambient-prompt index 6842240..bca9f35 100755 --- a/scripts/hooks/ambient-prompt +++ b/scripts/hooks/ambient-prompt @@ -40,7 +40,7 @@ fi # Inject classification preamble # SYNC: must match tests/integration/helpers.ts AMBIENT_PREAMBLE -PREAMBLE="AMBIENT MODE ACTIVE: Before responding, silently classify this prompt using the ambient-router skill already in your session context. If QUICK, respond normally without stating classification. If GUIDED or ORCHESTRATED, you MUST load the selected skills using the Skill tool before proceeding." +PREAMBLE="AMBIENT MODE ACTIVE: Before responding, silently classify this prompt using the ambient-router skill already in your session context. If QUICK, respond normally without stating classification. If GUIDED or ORCHESTRATED, your FIRST tool calls MUST be Skill tool invocations for each selected skill — before writing ANY text about the task." jq -n --arg ctx "$PREAMBLE" '{ "hookSpecificOutput": { diff --git a/shared/skills/ambient-router/SKILL.md b/shared/skills/ambient-router/SKILL.md index e97a8d0..67ae611 100644 --- a/shared/skills/ambient-router/SKILL.md +++ b/shared/skills/ambient-router/SKILL.md @@ -87,7 +87,9 @@ See `references/skill-catalog.md` for the full skill-to-intent mapping with file When classification is GUIDED or ORCHESTRATED, skill loading is NON-NEGOTIABLE. Do not rationalize skipping skills. Do not respond without loading them first. -BLOCKING REQUIREMENT: Invoke each selected skill using the Skill tool before proceeding. +BLOCKING REQUIREMENT: Your FIRST tool calls MUST be Skill tool invocations — before +writing ANY text about the task. Invoke all selected skills, THEN state classification, +THEN proceed with work. Do NOT write implementation text before all Skill tools return. For IMPLEMENT intent, enforce TDD: write the failing test before ANY production code. NOTE: Skills loaded in the main session via ambient mode are reference patterns only — their allowed-tools metadata does NOT restrict your tool access. You retain full access @@ -95,8 +97,8 @@ to all tools (Edit, Write, Bash, Agent, etc.) for implementation work. - **QUICK:** Respond directly. No preamble, no classification statement. -- **GUIDED:** State classification briefly: `Ambient: IMPLEMENT/GUIDED. Loading: implementation-patterns, search-first.` Then invoke each skill using the Skill tool and work directly in main session. After code changes, spawn Simplifier on changed files. -- **ORCHESTRATED:** State classification briefly: `Ambient: IMPLEMENT/ORCHESTRATED. Loading: implementation-orchestration, implementation-patterns.` Then invoke each skill using the Skill tool and follow Step 5 for agent orchestration. +- **GUIDED:** First, invoke each selected skill using the Skill tool. After all Skill tools return, state classification briefly: `Ambient: IMPLEMENT/GUIDED. Loading: implementation-patterns, search-first.` Then work directly in main session. After code changes, spawn Simplifier on changed files. +- **ORCHESTRATED:** First, invoke each selected skill using the Skill tool. After all Skill tools return, state classification briefly: `Ambient: IMPLEMENT/ORCHESTRATED. Loading: implementation-orchestration, implementation-patterns.` Then follow Step 5 for agent orchestration. ### GUIDED Behavior by Intent diff --git a/tests/ambient.test.ts b/tests/ambient.test.ts index deae8f1..fd99d1b 100644 --- a/tests/ambient.test.ts +++ b/tests/ambient.test.ts @@ -260,7 +260,7 @@ describe('preamble drift detection', () => { // The helpers.ts AMBIENT_PREAMBLE is used by extractIntent/extractDepth etc. // We verify it indirectly by checking the shell script value matches expected. const expectedPreamble = - 'AMBIENT MODE ACTIVE: Before responding, silently classify this prompt using the ambient-router skill already in your session context. If QUICK, respond normally without stating classification. If GUIDED or ORCHESTRATED, you MUST load the selected skills using the Skill tool before proceeding.'; + 'AMBIENT MODE ACTIVE: Before responding, silently classify this prompt using the ambient-router skill already in your session context. If QUICK, respond normally without stating classification. If GUIDED or ORCHESTRATED, your FIRST tool calls MUST be Skill tool invocations for each selected skill — before writing ANY text about the task.'; expect(shellPreamble).toBe(expectedPreamble); }); diff --git a/tests/integration/helpers.ts b/tests/integration/helpers.ts index eb6fa11..70c9d99 100644 --- a/tests/integration/helpers.ts +++ b/tests/integration/helpers.ts @@ -17,7 +17,7 @@ export function isClaudeAvailable(): boolean { // SYNC: must match scripts/hooks/ambient-prompt line 43 const AMBIENT_PREAMBLE = - 'AMBIENT MODE ACTIVE: Before responding, silently classify this prompt using the ambient-router skill already in your session context. If QUICK, respond normally without stating classification. If GUIDED or ORCHESTRATED, you MUST load the selected skills using the Skill tool before proceeding.'; + 'AMBIENT MODE ACTIVE: Before responding, silently classify this prompt using the ambient-router skill already in your session context. If QUICK, respond normally without stating classification. If GUIDED or ORCHESTRATED, your FIRST tool calls MUST be Skill tool invocations for each selected skill — before writing ANY text about the task.'; /** * Run a prompt through claude CLI in non-interactive mode.