fix formatting

This commit is contained in:
Joe Danziger
2025-05-09 12:21:51 -04:00
parent 476048b184
commit d48a3d3edc
7 changed files with 129 additions and 91 deletions

View File

@@ -218,6 +218,7 @@ task-master init --rules cursor,windsurf
- You can use multiple comma-separated brands in a single command. - You can use multiple comma-separated brands in a single command.
**Example:** **Example:**
```bash ```bash
task-master init --rules cursor,roo task-master init --rules cursor,roo
``` ```
@@ -238,6 +239,7 @@ task-master rules remove <brand1,brand2,...>
- You can use multiple comma-separated brands in a single command. - You can use multiple comma-separated brands in a single command.
**Examples:** **Examples:**
```bash ```bash
task-master rules add windsurf,roo task-master rules add windsurf,roo
task-master rules remove windsurf task-master rules remove windsurf

View File

@@ -80,9 +80,9 @@ export async function initializeProjectDirect(args, log, context = {}) {
// Handle rules option just like CLI // Handle rules option just like CLI
if (Array.isArray(args.rules) && args.rules.length > 0) { if (Array.isArray(args.rules) && args.rules.length > 0) {
options.rules = args.rules; options.rules = args.rules;
log.info(`Including brand rules: ${args.rules.join(", ")}`); log.info(`Including brand rules: ${args.rules.join(', ')}`);
} else { } else {
options.rules = ["cursor"]; options.rules = ['cursor'];
log.info(`No rules specified, defaulting to: cursor`); log.info(`No rules specified, defaulting to: cursor`);
} }

View File

@@ -24,7 +24,12 @@ export async function rulesDirect(args, log, context = {}) {
enableSilentMode(); enableSilentMode();
try { try {
const { action, rules, projectRoot, yes } = args; const { action, rules, projectRoot, yes } = args;
if (!action || !Array.isArray(rules) || rules.length === 0 || !projectRoot) { if (
!action ||
!Array.isArray(rules) ||
rules.length === 0 ||
!projectRoot
) {
return { return {
success: false, success: false,
error: { error: {
@@ -35,7 +40,8 @@ export async function rulesDirect(args, log, context = {}) {
} }
const rulesList = rules.join(','); const rulesList = rules.join(',');
const yesFlag = yes !== false ? '--yes' : ''; const yesFlag = yes !== false ? '--yes' : '';
const cmd = `npx task-master rules ${action} ${rulesList} ${yesFlag}`.trim(); const cmd =
`npx task-master rules ${action} ${rulesList} ${yesFlag}`.trim();
log.info(`[rulesDirect] Running: ${cmd} in ${projectRoot}`); log.info(`[rulesDirect] Running: ${cmd} in ${projectRoot}`);
const output = execSync(cmd, { cwd: projectRoot, encoding: 'utf8' }); const output = execSync(cmd, { cwd: projectRoot, encoding: 'utf8' });
log.info(`[rulesDirect] Output: ${output}`); log.info(`[rulesDirect] Output: ${output}`);

View File

@@ -39,7 +39,9 @@ export function registerInitializeProjectTool(server) {
rules: z rules: z
.array(z.string()) .array(z.string())
.optional() .optional()
.describe('List of brand rules to include at initialization (e.g., ["cursor", "roo"]). If omitted, defaults to ["cursor"].') .describe(
'List of brand rules to include at initialization (e.g., ["cursor", "roo"]). If omitted, defaults to ["cursor"].'
)
}), }),
execute: withNormalizedProjectRoot(async (args, context) => { execute: withNormalizedProjectRoot(async (args, context) => {
const { log } = context; const { log } = context;

View File

@@ -18,16 +18,34 @@ import { rulesDirect } from '../core/direct-functions/rules.js';
export function registerRulesTool(server) { export function registerRulesTool(server) {
server.addTool({ server.addTool({
name: 'rules', name: 'rules',
description: 'Add or remove brand rules and MCP config from the project (mirrors CLI rules add/remove).', description:
'Add or remove brand rules and MCP config from the project (mirrors CLI rules add/remove).',
parameters: z.object({ parameters: z.object({
action: z.enum(['add', 'remove']).describe('Whether to add or remove brand rules.'), action: z
rules: z.array(z.string()).min(1).describe('List of brand rules to add or remove (e.g., ["roo", "windsurf"]).'), .enum(['add', 'remove'])
projectRoot: z.string().describe('The root directory of the project. Must be an absolute path.'), .describe('Whether to add or remove brand rules.'),
yes: z.boolean().optional().default(true).describe('Run non-interactively (default: true).') rules: z
.array(z.string())
.min(1)
.describe(
'List of brand rules to add or remove (e.g., ["roo", "windsurf"]).'
),
projectRoot: z
.string()
.describe(
'The root directory of the project. Must be an absolute path.'
),
yes: z
.boolean()
.optional()
.default(true)
.describe('Run non-interactively (default: true).')
}), }),
execute: withNormalizedProjectRoot(async (args, { log, session }) => { execute: withNormalizedProjectRoot(async (args, { log, session }) => {
try { try {
log.info(`[rules tool] Executing action: ${args.action} for rules: ${args.rules.join(', ')} in ${args.projectRoot}`); log.info(
`[rules tool] Executing action: ${args.action} for rules: ${args.rules.join(', ')} in ${args.projectRoot}`
);
const result = await rulesDirect(args, log, { session }); const result = await rulesDirect(args, log, { session });
return handleApiResult(result, log); return handleApiResult(result, log);
} catch (error) { } catch (error) {

View File

@@ -319,7 +319,8 @@ async function initializeProject(options = {}) {
// } // }
const skipPrompts = options.yes || (options.name && options.description); const skipPrompts = options.yes || (options.name && options.description);
let selectedBrandRules = options.rules && Array.isArray(options.rules) && options.rules.length > 0 let selectedBrandRules =
options.rules && Array.isArray(options.rules) && options.rules.length > 0
? options.rules ? options.rules
: ['cursor']; : ['cursor'];
@@ -383,8 +384,8 @@ let selectedBrandRules = options.rules && Array.isArray(options.rules) && option
console.log('\nTask Master Project settings:'); console.log('\nTask Master Project settings:');
console.log( console.log(
chalk.blue( chalk.blue(
'Add shell aliases (so you can use "tm" instead of "task-master"):') 'Add shell aliases (so you can use "tm" instead of "task-master"):'
, ),
chalk.white(addAliasesPrompted ? 'Yes' : 'No') chalk.white(addAliasesPrompted ? 'Yes' : 'No')
); );
@@ -401,10 +402,11 @@ let selectedBrandRules = options.rules && Array.isArray(options.rules) && option
return; return;
} }
// === Brand Rules Selection (Inquirer) === // === Brand Rules Selection (Inquirer) ===
console.log( console.log(
chalk.cyan('\nRules help enforce best practices and conventions for Task Master.') chalk.cyan(
'\nRules help enforce best practices and conventions for Task Master.'
)
); );
const brandRulesQuestion = { const brandRulesQuestion = {
type: 'checkbox', type: 'checkbox',
@@ -417,7 +419,6 @@ let selectedBrandRules = options.rules && Array.isArray(options.rules) && option
const { brandRules } = await inquirer.prompt([brandRulesQuestion]); const { brandRules } = await inquirer.prompt([brandRulesQuestion]);
selectedBrandRules = brandRules; selectedBrandRules = brandRules;
const dryRun = options.dryRun || false; const dryRun = options.dryRun || false;
if (dryRun) { if (dryRun) {
@@ -468,7 +469,11 @@ function promptQuestion(rl, question) {
} }
// Function to create the project structure // Function to create the project structure
function createProjectStructure(addAliases, dryRun, selectedBrandRules = ['cursor']) { function createProjectStructure(
addAliases,
dryRun,
selectedBrandRules = ['cursor']
) {
const targetDir = process.cwd(); const targetDir = process.cwd();
log('info', `Initializing project in ${targetDir}`); log('info', `Initializing project in ${targetDir}`);

View File

@@ -15,14 +15,19 @@ const mockLogger = {
}; };
// Use a temp directory for testing (simulate a project root) // Use a temp directory for testing (simulate a project root)
const tempProjectRoot = path.join(__dirname, '../../fixtures/temp-rules-project'); const tempProjectRoot = path.join(
__dirname,
'../../fixtures/temp-rules-project'
);
beforeAll(() => { beforeAll(() => {
if (!fs.existsSync(tempProjectRoot)) fs.mkdirSync(tempProjectRoot, { recursive: true }); if (!fs.existsSync(tempProjectRoot))
fs.mkdirSync(tempProjectRoot, { recursive: true });
}); });
afterAll(() => { afterAll(() => {
if (fs.existsSync(tempProjectRoot)) fs.rmSync(tempProjectRoot, { recursive: true, force: true }); if (fs.existsSync(tempProjectRoot))
fs.rmSync(tempProjectRoot, { recursive: true, force: true });
}); });
describe('rulesDirect (integration)', () => { describe('rulesDirect (integration)', () => {