mirror of
https://github.com/eyaltoledano/claude-task-master.git
synced 2026-01-30 06:12:05 +00:00
📝 Add docstrings to fix-ai-sdk-jsonschema-fallback
Docstrings generation was requested by @TheLazyIndianTechie. * https://github.com/eyaltoledano/claude-task-master/pull/1556#issuecomment-3703582946 The following files were modified: * `scripts/modules/task-manager/parse-prd/parse-prd-helpers.js` * `scripts/modules/task-manager/scope-adjustment.js`
This commit is contained in:
committed by
GitHub
parent
1d8d72315f
commit
bd163b6c62
@@ -120,19 +120,21 @@ export function validateFileOperations({
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process and transform tasks with ID remapping
|
* Transform raw PRD tasks into normalized tasks with reassigned sequential IDs.
|
||||||
* @param {Array} rawTasks - Raw tasks from AI
|
* @param {Array} rawTasks - Tasks parsed from a PRD; each task must include an integer `id`.
|
||||||
* @param {number} startId - Starting ID for new tasks
|
* @param {number} startId - ID to assign to the first processed task.
|
||||||
* @param {Array} existingTasks - Existing tasks for dependency validation
|
* @param {Array} existingTasks - Existing tasks used to validate dependency references.
|
||||||
* @param {string} defaultPriority - Default priority for tasks
|
* @param {string} defaultPriority - Priority to apply when a task has no priority.
|
||||||
* @returns {Array} Processed tasks with remapped IDs
|
* @returns {Array} An array of tasks with reassigned sequential IDs, normalized fields (status, priority, title, description, details, testStrategy, subtasks), and dependencies remapped to the new IDs.
|
||||||
*/
|
|
||||||
export function processTasks(
|
export function processTasks(
|
||||||
rawTasks,
|
rawTasks,
|
||||||
startId,
|
startId,
|
||||||
existingTasks,
|
existingTasks,
|
||||||
defaultPriority
|
defaultPriority
|
||||||
) {
|
) {
|
||||||
|
// Runtime guard: ensure PRD task IDs are unique and sequential (1..N).
|
||||||
|
validateSequentialTaskIds(rawTasks, startId);
|
||||||
|
|
||||||
let currentId = startId;
|
let currentId = startId;
|
||||||
const taskMap = new Map();
|
const taskMap = new Map();
|
||||||
|
|
||||||
@@ -172,6 +174,54 @@ export function processTasks(
|
|||||||
return processedTasks;
|
return processedTasks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate that an array of PRD tasks uses unique, positive integer IDs that form a contiguous sequence.
|
||||||
|
*
|
||||||
|
* Validates that each task has an integer `id` >= 1, that IDs are unique, and that the sorted IDs form
|
||||||
|
* a contiguous sequence starting at either `1` or the provided `expectedStartId`.
|
||||||
|
*
|
||||||
|
* @param {Array<{id: number}>} rawTasks - Array of task objects containing an `id` property. If not an array or empty, no validation is performed.
|
||||||
|
* @param {number} [expectedStartId=1] - Allowed alternative starting ID for the contiguous sequence.
|
||||||
|
* @throws {Error} If any `id` is not an integer >= 1: "PRD tasks must use sequential positive integer IDs starting at 1."
|
||||||
|
* @throws {Error} If IDs are not unique: "PRD task IDs must be unique and sequential starting at 1."
|
||||||
|
* @throws {Error} If the sequence does not start at `1` or `expectedStartId`: "PRD task IDs must start at 1 or {expectedStartId} and be sequential."
|
||||||
|
* @throws {Error} If IDs are not contiguous: "PRD task IDs must be a contiguous sequence starting at {startId}."
|
||||||
|
*/
|
||||||
|
function validateSequentialTaskIds(rawTasks, expectedStartId = 1) {
|
||||||
|
if (!Array.isArray(rawTasks) || rawTasks.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ids = rawTasks.map((task) => task.id);
|
||||||
|
|
||||||
|
if (ids.some((id) => !Number.isInteger(id) || id < 1)) {
|
||||||
|
throw new Error(
|
||||||
|
'PRD tasks must use sequential positive integer IDs starting at 1.'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const uniqueIds = new Set(ids);
|
||||||
|
if (uniqueIds.size !== ids.length) {
|
||||||
|
throw new Error('PRD task IDs must be unique and sequential starting at 1.');
|
||||||
|
}
|
||||||
|
|
||||||
|
const sortedIds = [...uniqueIds].sort((a, b) => a - b);
|
||||||
|
const startId = sortedIds[0];
|
||||||
|
if (startId !== 1 && startId !== expectedStartId) {
|
||||||
|
throw new Error(
|
||||||
|
`PRD task IDs must start at 1 or ${expectedStartId} and be sequential.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let index = 0; index < sortedIds.length; index += 1) {
|
||||||
|
if (sortedIds[index] !== startId + index) {
|
||||||
|
throw new Error(
|
||||||
|
`PRD task IDs must be a contiguous sequence starting at ${startId}.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Save tasks to file with tag support
|
* Save tasks to file with tag support
|
||||||
* @param {string} tasksPath - Path to save tasks
|
* @param {string} tasksPath - Path to save tasks
|
||||||
@@ -380,4 +430,4 @@ export function displayNonStreamingCliOutput({
|
|||||||
if (aiServiceResponse?.telemetryData) {
|
if (aiServiceResponse?.telemetryData) {
|
||||||
displayAiUsageSummary(aiServiceResponse.telemetryData, 'cli');
|
displayAiUsageSummary(aiServiceResponse.telemetryData, 'cli');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -157,14 +157,22 @@ function getCurrentComplexityScore(taskId, context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Regenerates subtasks for a task based on new complexity while preserving completed work
|
* Regenerates a task's pending subtasks to match a changed complexity while preserving subtasks with work already done.
|
||||||
* @param {Object} task - The updated task object
|
*
|
||||||
* @param {string} tasksPath - Path to tasks.json
|
* Generates new pending subtasks (via the configured AI service) to reach a target subtask count based on direction and strength, preserves subtasks whose status indicates work should be kept, and remaps IDs/dependencies so generated subtasks follow preserved ones.
|
||||||
* @param {Object} context - Context containing projectRoot, tag, session
|
*
|
||||||
* @param {string} direction - Direction of scope change (up/down) for logging
|
* @param {Object} task - The task object to update; its subtasks array will be replaced with preserved and newly generated subtasks in the returned `updatedTask`.
|
||||||
* @param {string} strength - Strength level ('light', 'regular', 'heavy')
|
* @param {string} tasksPath - Filesystem path to tasks.json (used for context; not modified by this function).
|
||||||
* @param {number|null} originalComplexity - Original complexity score for smarter adjustments
|
* @param {Object} context - Execution context containing { projectRoot, tag, session, ... } used for AI calls and logging.
|
||||||
* @returns {Promise<Object>} Object with updated task and regeneration info
|
* @param {string} direction - Scope change direction: 'up' to increase complexity or 'down' to decrease complexity.
|
||||||
|
* @param {string} [strength='regular'] - Adjustment strength: 'light', 'regular', or 'heavy'.
|
||||||
|
* @param {number|null} [originalComplexity=null] - Original complexity score (1-10) used to bias how aggressive the adjustment should be.
|
||||||
|
* @returns {Promise<Object>} An object with:
|
||||||
|
* - updatedTask: the task object with preserved and regenerated subtasks,
|
||||||
|
* - regenerated: `true` if new subtasks were generated, `false` otherwise,
|
||||||
|
* - preserved: number of subtasks kept,
|
||||||
|
* - generated: number of subtasks newly generated,
|
||||||
|
* - error?: string when regeneration failed (present only on failure).
|
||||||
*/
|
*/
|
||||||
async function regenerateSubtasksForComplexity(
|
async function regenerateSubtasksForComplexity(
|
||||||
task,
|
task,
|
||||||
@@ -378,6 +386,7 @@ Ensure the JSON is valid and properly formatted.`;
|
|||||||
});
|
});
|
||||||
|
|
||||||
const generatedSubtasks = aiResult.mainResult.subtasks || [];
|
const generatedSubtasks = aiResult.mainResult.subtasks || [];
|
||||||
|
ensureSequentialSubtaskIds(generatedSubtasks);
|
||||||
|
|
||||||
// Post-process generated subtasks to ensure defaults
|
// Post-process generated subtasks to ensure defaults
|
||||||
const processedGeneratedSubtasks = generatedSubtasks.map((subtask) => ({
|
const processedGeneratedSubtasks = generatedSubtasks.map((subtask) => ({
|
||||||
@@ -441,6 +450,38 @@ Ensure the JSON is valid and properly formatted.`;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate that subtasks have unique, positive integer IDs forming a sequential series starting at 1.
|
||||||
|
*
|
||||||
|
* @param {Array<object>} subtasks - Array of subtask objects; each object is expected to have an `id` property.
|
||||||
|
* @throws {Error} If any `id` is not a positive integer ("Generated subtask ids must be positive integers").
|
||||||
|
* @throws {Error} If `id` values are not unique ("Generated subtasks must have unique ids").
|
||||||
|
* @throws {Error} If `id` values are not a contiguous sequence starting at 1 ("Generated subtask ids must be sequential starting from 1").
|
||||||
|
*/
|
||||||
|
function ensureSequentialSubtaskIds(subtasks) {
|
||||||
|
if (!Array.isArray(subtasks) || subtasks.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ids = subtasks.map((subtask) => subtask.id);
|
||||||
|
if (ids.some((id) => !Number.isInteger(id) || id < 1)) {
|
||||||
|
throw new Error('Generated subtask ids must be positive integers');
|
||||||
|
}
|
||||||
|
const uniqueIds = new Set(ids);
|
||||||
|
if (uniqueIds.size !== ids.length) {
|
||||||
|
throw new Error('Generated subtasks must have unique ids');
|
||||||
|
}
|
||||||
|
|
||||||
|
const sortedIds = [...uniqueIds].sort((a, b) => a - b);
|
||||||
|
for (let index = 0; index < sortedIds.length; index += 1) {
|
||||||
|
if (sortedIds[index] !== index + 1) {
|
||||||
|
throw new Error(
|
||||||
|
'Generated subtask ids must be sequential starting from 1'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates AI prompt for scope adjustment
|
* Generates AI prompt for scope adjustment
|
||||||
* @param {Object} task - The task to adjust
|
* @param {Object} task - The task to adjust
|
||||||
@@ -872,4 +913,4 @@ export async function scopeDownTask(
|
|||||||
updatedTasks,
|
updatedTasks,
|
||||||
telemetryData: combinedTelemetryData
|
telemetryData: combinedTelemetryData
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user