/** * Task reparenting, promotion, and reopen operations. * @task T10064 * @epic T9834 */ /** * Move a task and its descendants under a different parent. * * @param projectRoot - Absolute path to the CLEO project root directory * @param taskId - The task ID to reparent * @param newParentId - The new parent task ID, or null to promote to root level * @returns Confirmation with old/new parent IDs, reopened ancestors, and the updated subtree IDs * * @remarks * Validates circular references, depth limits, sibling limits, and the PM-Core * V2 parent/type matrix before writing. Reparenting moves the whole subtree; * Saga and Epic types are preserved while Task/Subtask descendants are adjusted * only when their new parent tier requires it. * * @example * ```typescript * const result = await coreTaskReparent('/project', 'T015', 'T010'); * console.log(`Moved from ${result.oldParent} to ${result.newParent}`); * ``` * * @task T4790 */ export declare function coreTaskReparent(projectRoot: string, taskId: string, newParentId: string | null): Promise<{ task: string; reparented: boolean; oldParent: string | null; newParent: string | null; newType?: string; ancestorsReopened: string[]; subtreeUpdated: string[]; }>; /** * Promote a subtask to task or task to root. * * @param projectRoot - Absolute path to the CLEO project root directory * @param taskId - The task ID to promote * @returns Confirmation with previous parent and whether the type changed * * @remarks * Removes the task's parentId, making it a root-level task. If the task was * a "subtask", its type is changed to "task". No-op if the task is already root-level. * * @example * ```typescript * const result = await coreTaskPromote('/project', 'T025'); * if (result.promoted) console.log('Detached from', result.previousParent); * ``` * * @task T4790 */ export declare function coreTaskPromote(projectRoot: string, taskId: string): Promise<{ task: string; promoted: boolean; previousParent: string | null; typeChanged: boolean; }>; /** * Reopen a completed task. * * @param projectRoot - Absolute path to the CLEO project root directory * @param taskId - The completed task ID to reopen * @param params - Optional reopen options * @param params.status - Target status after reopening ("pending" or "active", default: "pending") * @param params.reason - Optional reason appended to the task's notes * @param params.regressionOf - Optional task ID this reopen is a regression of (AC2: regression_of path documented) * @param params.reopenAncestors - When true (default), reopen any done ancestors in the hierarchy (AC1) * @returns Confirmation with previous and new status, plus any ancestor IDs that were reopened * * @remarks * Only tasks with status "done" can be reopened. Preserves the prior `completedAt` timestamp * in the task's notes before clearing it (AC3: completion history preserved). When * `reopenAncestors` is true, all done ancestors are also set back to "pending" so the * hierarchy reflects the unsatisfied state (AC1: required unsatisfied child reopens ancestors). * When `regressionOf` is supplied, a note is appended that links the reopen to the original * completed task (AC2: regression_of path documented). * * @example * ```typescript * const result = await coreTaskReopen('/project', 'T033', { * status: 'active', * reason: 'Tests failed', * regressionOf: 'T033', * reopenAncestors: true, * }); * console.log(`${result.previousStatus} -> ${result.newStatus}, ancestors: ${result.ancestorsReopened}`); * ``` * * @task T4790 * @task T10605 */ export declare function coreTaskReopen(projectRoot: string, taskId: string, params?: { status?: string; reason?: string; /** Task ID that this reopen is a regression of. Appended to notes for traceability. */ regressionOf?: string; /** When true (default), reopen any done ancestors so the hierarchy is consistent. */ reopenAncestors?: boolean; }): Promise<{ task: string; reopened: boolean; previousStatus: string; newStatus: string; /** IDs of ancestor tasks that were transitioned from done → pending. */ ancestorsReopened: string[]; }>; /** * Change task position within its sibling group. * * @param projectRoot - Absolute path to the CLEO project root directory * @param taskId - The task ID to reorder * @param position - Target 1-based position within the sibling group * @returns Confirmation with the new position and total sibling count * * @remarks * Reorders by adjusting `position` and `positionVersion` fields on all siblings. * Position is clamped to valid bounds. Uses bulk field updates for efficiency. * * @example * ```typescript * const result = await coreTaskReorder('/project', 'T012', 1); * console.log(`Moved to position ${result.newPosition} of ${result.totalSiblings}`); * ``` * * @task T4790 */ export declare function coreTaskReorder(projectRoot: string, taskId: string, position: number): Promise<{ task: string; reordered: boolean; newPosition: number; totalSiblings: number; }>; /** * Re-rank a column/sibling scope from an explicit top-to-bottom task-ID order. * * Unlike {@link coreTaskReorder} (which moves ONE task to a 1-based index and * recomputes every sibling), this persists a FULL desired ordering in one pass: * each task's `position` is set to its 1-based index in `orderedIds` and its * `positionVersion` is bumped for optimistic concurrency. This is the Kanban * "drag a card and the whole column re-ranks" shape — the client sends the new * column order and the op writes it. IDs that do not resolve to a task are * collected in `skipped` rather than failing the batch. * * @param projectRoot - Absolute path to the CLEO project root directory. * @param orderedIds - Task IDs in the desired top-to-bottom order. * @returns The re-ranked IDs (new order), any skipped IDs, and the rank count. * * @example * ```typescript * await coreTaskReorderRank('/project', ['T3', 'T1', 'T2']); * // T3.position=1, T1.position=2, T2.position=3 * ``` * * @task T11786 * @epic T11556 */ export declare function coreTaskReorderRank(projectRoot: string, orderedIds: string[]): Promise<{ ranked: string[]; skipped: string[]; count: number; }>; /** * Atomically move N tasks to a new status and/or pipeline stage. * * The Kanban "select N cards, drop them in a new column" shape. Every move runs * inside a SINGLE DB transaction, so any failure rolls back ALL moves * (all-or-nothing). At least one of `status` / `pipelineStage` MUST be supplied, * and `status` (when present) MUST be a valid {@link TaskStatus}. * * @param projectRoot - Absolute path to the CLEO project root directory. * @param taskIds - The task IDs to move (non-empty). * @param target - The new `status` and/or `pipelineStage` to apply. * @returns The moved IDs plus the applied status/stage and the move count. * @throws Error when no target is supplied, `status` is invalid, or any task ID * does not resolve (the whole transaction is then rolled back). * * @example * ```typescript * await coreTaskBulkMove('/project', ['T1', 'T2'], { status: 'active' }); * ``` * * @task T11786 * @epic T11556 */ export declare function coreTaskBulkMove(projectRoot: string, taskIds: string[], target: { status?: string; pipelineStage?: string; }): Promise<{ moved: string[]; status?: string; pipelineStage?: string; count: number; }>; /** * Set or clear a task's first-class assignee. * * A first-class owner/assignee surface DISTINCT from the agent claim lock: * {@link coreTaskReorder} aside, agent claim/unclaim performs a CONDITIONAL * atomic claim (`WHERE assignee IS NULL OR assignee = agentId`) with lock * semantics, whereas this op is a DIRECT unconditional set/clear an operator or * Studio board drives. Pass `assignee = null`/empty to clear. * * @param projectRoot - Absolute path to the CLEO project root directory. * @param taskId - The task ID whose assignee is set or cleared. * @param assignee - The assignee to set, or `null`/empty to clear. * @returns The task ID, the new assignee value, and whether one was set. * @throws Error when the task does not exist. * * @example * ```typescript * await coreTaskAssignee('/project', 'T1', 'alice'); // set * await coreTaskAssignee('/project', 'T1', null); // clear * ``` * * @task T11786 * @epic T11556 */ export declare function coreTaskAssignee(projectRoot: string, taskId: string, assignee: string | null | undefined): Promise<{ taskId: string; assignee: string | null; assigned: boolean; }>; /** * Restore a cancelled task back to pending. * * @param projectRoot - Absolute path to the CLEO project root directory * @param taskId - The cancelled task ID to restore * @param params - Optional restore options * @param params.cascade - When true, also restores cancelled child tasks recursively * @param params.notes - Optional note appended to each restored task's notes array * @returns The task ID, list of restored task IDs, and total count * * @remarks * Only tasks with status "cancelled" can be restored. Restored tasks are set to * "pending" with cancellation metadata cleared. A timestamped note is appended. * * @example * ```typescript * const { restored, count } = await coreTaskRestore('/project', 'T099', { cascade: true }); * console.log(`Restored ${count} tasks:`, restored); * ``` * * @task T4790 */ export declare function coreTaskRestore(projectRoot: string, taskId: string, params?: { cascade?: boolean; notes?: string; }): Promise<{ task: string; restored: string[]; count: number; }>; /** * Move an archived task back to active tasks. * * @param projectRoot - Absolute path to the CLEO project root directory * @param taskId - The archived task ID to unarchive * @param params - Optional unarchive options * @param params.status - Target status for the restored task (default: "pending") * @param params.preserveStatus - When true, keeps the task's original archived status * @returns Confirmation with task ID, title, and resulting status * * @remarks * Removes the task from the archive file and upserts it into the active task store. * Throws if the task already exists in active tasks or is not found in the archive. * * @example * ```typescript * const result = await coreTaskUnarchive('/project', 'T055', { status: 'active' }); * console.log(`${result.title} is now ${result.status}`); * ``` * * @task T4790 */ export declare function coreTaskUnarchive(projectRoot: string, taskId: string, params?: { status?: string; preserveStatus?: boolean; }): Promise<{ task: string; unarchived: boolean; title: string; status: string; }>; //# sourceMappingURL=task-reparent.d.ts.map