mirror of
https://github.com/wassname/pi-lgtm.git
synced 2026-06-27 15:31:29 +08:00
96 lines
3.0 KiB
TypeScript
96 lines
3.0 KiB
TypeScript
/**
|
|
* auto-clear.ts — Turn-based auto-clearing of completed tasks.
|
|
*
|
|
* Two modes:
|
|
* - "on_task_complete": each completed task gets its own REMINDER_INTERVAL countdown, deleted individually
|
|
* - "on_list_complete": countdown starts when ALL tasks are completed, cleared as a batch
|
|
*
|
|
* Both use the same turn delay (REMINDER_INTERVAL) for consistency.
|
|
*/
|
|
|
|
import type { TaskStore } from "./task-store.js";
|
|
|
|
export type AutoClearMode = "never" | "on_list_complete" | "on_task_complete";
|
|
|
|
export class AutoClearManager {
|
|
/** Per-task: turn when task was marked completed ("on_task_complete" mode). */
|
|
private completedAtTurn = new Map<string, number>();
|
|
/** Turn when ALL tasks became completed ("on_list_complete" mode). */
|
|
private allCompletedAtTurn: number | null = null;
|
|
|
|
constructor(
|
|
private getStore: () => TaskStore,
|
|
private getMode: () => AutoClearMode,
|
|
/** How many turns completed tasks linger before auto-clearing. */
|
|
private clearDelayTurns = 4,
|
|
) {}
|
|
|
|
/** Record a task completion. Call AFTER cascade logic. */
|
|
trackCompletion(taskId: string, currentTurn: number): void {
|
|
const mode = this.getMode();
|
|
if (mode === "never") return;
|
|
|
|
if (mode === "on_task_complete") {
|
|
this.completedAtTurn.set(taskId, currentTurn);
|
|
} else if (mode === "on_list_complete") {
|
|
this.checkAllCompleted(currentTurn);
|
|
}
|
|
}
|
|
|
|
/** Check if all tasks are completed and start/reset the batch countdown. */
|
|
private checkAllCompleted(currentTurn: number): void {
|
|
const tasks = this.getStore().list();
|
|
if (tasks.length > 0 && tasks.every((t) => t.status === "completed")) {
|
|
if (this.allCompletedAtTurn === null)
|
|
this.allCompletedAtTurn = currentTurn;
|
|
} else {
|
|
this.allCompletedAtTurn = null;
|
|
}
|
|
}
|
|
|
|
/** Reset batch countdown (e.g., when a new task is created or task goes non-completed). */
|
|
resetBatchCountdown(): void {
|
|
this.allCompletedAtTurn = null;
|
|
}
|
|
|
|
/** Reset all tracking state (e.g., on new session). */
|
|
reset(): void {
|
|
this.completedAtTurn.clear();
|
|
this.allCompletedAtTurn = null;
|
|
}
|
|
|
|
/**
|
|
* Called on each turn start. Deletes tasks whose linger period has expired.
|
|
* Returns true if any tasks were cleared.
|
|
*/
|
|
onTurnStart(currentTurn: number): boolean {
|
|
const mode = this.getMode();
|
|
let cleared = false;
|
|
|
|
if (mode === "on_task_complete") {
|
|
for (const [taskId, turn] of this.completedAtTurn) {
|
|
const task = this.getStore().get(taskId);
|
|
if (!task || task.status !== "completed") {
|
|
// Task was deleted or reverted — drop stale tracking entry
|
|
this.completedAtTurn.delete(taskId);
|
|
} else if (currentTurn - turn >= this.clearDelayTurns) {
|
|
this.getStore().delete(taskId);
|
|
this.completedAtTurn.delete(taskId);
|
|
cleared = true;
|
|
}
|
|
}
|
|
} else if (
|
|
mode === "on_list_complete" &&
|
|
this.allCompletedAtTurn !== null
|
|
) {
|
|
if (currentTurn - this.allCompletedAtTurn >= this.clearDelayTurns) {
|
|
this.getStore().clearCompleted();
|
|
this.allCompletedAtTurn = null;
|
|
cleared = true;
|
|
}
|
|
}
|
|
|
|
return cleared;
|
|
}
|
|
}
|