feat: Centralize AI prompts into JSON templates (#882)

* centralize prompt management

* add changeset

* add variant key to determine prompt version

* update tests and add prompt manager test

* determine internal path, don't use projectRoot

* add promptManager mock

* detailed prompt docs

* add schemas and validator packages

* add validate prompts command

* add schema validation

* update tests

* move schemas to src/prompts/schemas

* use this.promptsDir for better semantics

* add prompt schemas

* version schema files & update links

* remove validate command

* expect dependencies

* update docs

* fix test

* remove suggestmode to ensure clean keys

* remove default variant from research and update schema

* now handled by prompt manager

* add manual test to verify prompts

* remove incorrect batch variant

* consolidate variants

* consolidate analyze-complexity to just default variant

* consolidate parse-prd variants

* add eq handler for handlebars

* consolidate research prompt variants

* use brevity

* consolidate variants for update subtask

* add not handler

* consolidate variants for update-task

* consolidate update-tasks variants

* add conditional content to prompt when research used

* update prompt tests

* show correct research variant

* make variant names link to below

* remove changset

* restore gitignore

* Merge branch 'next' of https://github.com/eyaltoledano/claude-task-master into joedanz/centralize-prompts

# Conflicts:
#	package-lock.json
#	scripts/modules/task-manager/expand-task.js
#	scripts/modules/task-manager/parse-prd.js

remove unused

* add else

* update tests

* update biome optional dependencies

* responsive html output for mobile
This commit is contained in:
Joe Danziger
2025-07-10 03:52:11 -04:00
committed by GitHub
parent 4bc8029080
commit a65ad0a47c
36 changed files with 6180 additions and 9034 deletions

View File

@@ -171,6 +171,18 @@ jest.unstable_mockModule('fs', () => ({
writeFileSync: mockWriteFileSync
}));
jest.unstable_mockModule(
'../../../../../scripts/modules/prompt-manager.js',
() => ({
getPromptManager: jest.fn().mockReturnValue({
loadPrompt: jest.fn().mockResolvedValue({
systemPrompt: 'Mocked system prompt',
userPrompt: 'Mocked user prompt'
})
})
})
);
// Import the mocked modules
const { readJSON, writeJSON, log, CONFIG } = await import(
'../../../../../scripts/modules/utils.js'
@@ -262,11 +274,13 @@ describe('analyzeTaskComplexity', () => {
file: 'tasks/tasks.json',
output: 'scripts/task-complexity-report.json',
threshold: '5',
research: false
research: false,
projectRoot: '/mock/project/root'
};
// Act
await analyzeTaskComplexity(options, {
projectRoot: '/mock/project/root',
mcpLog: {
info: jest.fn(),
warn: jest.fn(),
@@ -279,7 +293,7 @@ describe('analyzeTaskComplexity', () => {
// Assert
expect(readJSON).toHaveBeenCalledWith(
'tasks/tasks.json',
undefined,
'/mock/project/root',
undefined
);
expect(generateTextService).toHaveBeenCalledWith(expect.any(Object));
@@ -296,11 +310,13 @@ describe('analyzeTaskComplexity', () => {
file: 'tasks/tasks.json',
output: 'scripts/task-complexity-report.json',
threshold: '5',
research: true
research: true,
projectRoot: '/mock/project/root'
};
// Act
await analyzeTaskComplexity(researchOptions, {
projectRoot: '/mock/project/root',
mcpLog: {
info: jest.fn(),
warn: jest.fn(),
@@ -323,10 +339,12 @@ describe('analyzeTaskComplexity', () => {
let options = {
file: 'tasks/tasks.json',
output: 'scripts/task-complexity-report.json',
threshold: '7'
threshold: '7',
projectRoot: '/mock/project/root'
};
await analyzeTaskComplexity(options, {
projectRoot: '/mock/project/root',
mcpLog: {
info: jest.fn(),
warn: jest.fn(),
@@ -349,10 +367,12 @@ describe('analyzeTaskComplexity', () => {
options = {
file: 'tasks/tasks.json',
output: 'scripts/task-complexity-report.json',
threshold: 8
threshold: 8,
projectRoot: '/mock/project/root'
};
await analyzeTaskComplexity(options, {
projectRoot: '/mock/project/root',
mcpLog: {
info: jest.fn(),
warn: jest.fn(),
@@ -374,11 +394,13 @@ describe('analyzeTaskComplexity', () => {
const options = {
file: 'tasks/tasks.json',
output: 'scripts/task-complexity-report.json',
threshold: '5'
threshold: '5',
projectRoot: '/mock/project/root'
};
// Act
await analyzeTaskComplexity(options, {
projectRoot: '/mock/project/root',
mcpLog: {
info: jest.fn(),
warn: jest.fn(),
@@ -402,7 +424,8 @@ describe('analyzeTaskComplexity', () => {
const options = {
file: 'tasks/tasks.json',
output: 'scripts/task-complexity-report.json',
threshold: '5'
threshold: '5',
projectRoot: '/mock/project/root'
};
// Force API error
@@ -419,6 +442,7 @@ describe('analyzeTaskComplexity', () => {
// Act & Assert
await expect(
analyzeTaskComplexity(options, {
projectRoot: '/mock/project/root',
mcpLog: mockMcpLog
})
).rejects.toThrow('API Error');