diff --git a/src/backends/adapter.ts b/src/backends/adapter.ts index f376210b..20b2a65a 100644 --- a/src/backends/adapter.ts +++ b/src/backends/adapter.ts @@ -82,7 +82,7 @@ function getToolManifests(): ToolManifest[] { parameters: { workItemId: { type: 'string', required: true }, name: { type: 'string', required: true }, - items: { type: 'array', required: true }, + item: { type: 'array', required: true }, }, }, { diff --git a/src/backends/claude-code/index.ts b/src/backends/claude-code/index.ts index c2fc737f..e0d0c87a 100644 --- a/src/backends/claude-code/index.ts +++ b/src/backends/claude-code/index.ts @@ -19,6 +19,20 @@ import type { import { buildHooks } from './hooks.js'; import { CLAUDE_CODE_MODEL_IDS, DEFAULT_CLAUDE_CODE_MODEL } from './models.js'; +/** + * Format a single CLI parameter for tool guidance documentation. + */ +function formatParam(key: string, schema: { type: string; required?: boolean }): string { + if (schema.type === 'array') { + // Array params use repeated flags: --item "a" --item "b" + const singular = key.replace(/s$/, ''); + return schema.required + ? ` --${singular} (repeatable)` + : ` [--${singular} (repeatable)]`; + } + return schema.required ? ` --${key} <${schema.type}>` : ` [--${key} <${schema.type}>]`; +} + /** * Build prompt guidance for CASCADE-specific CLI tools. * The Claude Code agent invokes these via its built-in Bash tool. @@ -41,8 +55,7 @@ export function buildToolGuidance(tools: ToolManifest[]): string { guidance += `\`\`\`bash\n${tool.cliCommand}`; for (const [key, schema] of Object.entries(tool.parameters)) { - const s = schema as { type: string; required?: boolean }; - guidance += s.required ? ` --${key} <${s.type}>` : ` [--${key} <${s.type}>]`; + guidance += formatParam(key, schema as { type: string; required?: boolean }); } guidance += '\n```\n\n'; diff --git a/src/cli/pm/add-checklist.ts b/src/cli/pm/add-checklist.ts index aa271d2e..80ef2470 100644 --- a/src/cli/pm/add-checklist.ts +++ b/src/cli/pm/add-checklist.ts @@ -8,8 +8,8 @@ export default class AddChecklist extends CredentialScopedCommand { static override flags = { workItemId: Flags.string({ description: 'The work item ID', required: true }), name: Flags.string({ description: 'Checklist name', required: true }), - items: Flags.string({ - description: 'Checklist items (can be specified multiple times)', + item: Flags.string({ + description: 'Checklist item (repeatable, specify multiple times)', required: true, multiple: true, }), @@ -20,7 +20,7 @@ export default class AddChecklist extends CredentialScopedCommand { const result = await addChecklist({ workItemId: flags.workItemId, checklistName: flags.name, - items: flags.items, + items: flags.item, }); this.log(JSON.stringify({ success: true, data: result })); } diff --git a/tests/unit/backends/claude-code.test.ts b/tests/unit/backends/claude-code.test.ts index ceb97a02..1dc8c169 100644 --- a/tests/unit/backends/claude-code.test.ts +++ b/tests/unit/backends/claude-code.test.ts @@ -112,6 +112,38 @@ describe('buildToolGuidance', () => { const guidance = buildToolGuidance(sampleTools); expect(guidance).toContain('[--includeComments ]'); }); + + it('renders array params as repeatable flags with singular name', () => { + const tools: ToolManifest[] = [ + { + name: 'AddChecklist', + description: 'Add a checklist.', + cliCommand: 'cascade-tools pm add-checklist', + parameters: { + workItemId: { type: 'string', required: true }, + item: { type: 'array', required: true }, + }, + }, + ]; + const guidance = buildToolGuidance(tools); + expect(guidance).toContain('--item (repeatable)'); + expect(guidance).not.toContain(''); + }); + + it('renders optional array params with brackets and repeatable hint', () => { + const tools: ToolManifest[] = [ + { + name: 'TestTool', + description: 'Test.', + cliCommand: 'cascade-tools test', + parameters: { + tags: { type: 'array' }, + }, + }, + ]; + const guidance = buildToolGuidance(tools); + expect(guidance).toContain('[--tag (repeatable)]'); + }); }); describe('buildTaskPrompt', () => {