-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathstore.ts
More file actions
73 lines (65 loc) · 2.23 KB
/
store.ts
File metadata and controls
73 lines (65 loc) · 2.23 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
/**
* Sprint storage — persists sprint history per project.
*
* Stores sprint records in ~/.pi/sprint/{hash}.json
* The markdown report file is the primary source of truth for task progress.
*/
import * as crypto from "node:crypto";
import * as fs from "node:fs";
import * as os from "node:os";
import * as path from "node:path";
import type { SprintTask } from "./parser.js";
export interface SprintRecord {
id: string;
createdAt: number;
title: string;
status: "pending" | "accepted" | "executing" | "paused" | "completed" | "rejected" | "failed";
proposal: string;
critique: string | null;
synthesis: string;
snapshotSummary: string;
tasks: SprintTask[];
currentTaskIndex: number;
reportPath?: string;
}
interface SprintFile {
version: 2;
sprints: SprintRecord[];
}
export function sprintStoragePath(cwd: string): string {
const hash = crypto.createHash("sha256").update(cwd).digest("hex").slice(0, 16);
return path.join(os.homedir(), ".pi", "sprint", `${hash}.json`);
}
export function loadSprints(storagePath: string): SprintRecord[] {
if (!fs.existsSync(storagePath)) return [];
try {
const raw = JSON.parse(fs.readFileSync(storagePath, "utf-8")) as Partial<SprintFile>;
return Array.isArray(raw.sprints) ? raw.sprints : [];
} catch {
return [];
}
}
export function saveSprints(storagePath: string, sprints: SprintRecord[]): void {
const dir = path.dirname(storagePath);
fs.mkdirSync(dir, { recursive: true });
const payload: SprintFile = { version: 2, sprints };
const tmp = `${storagePath}.tmp`;
fs.writeFileSync(tmp, JSON.stringify(payload, null, 2));
fs.renameSync(tmp, storagePath);
}
/** Save a single sprint record (find by id and update, or append). */
export function saveSprint(storagePath: string, record: SprintRecord): void {
const sprints = loadSprints(storagePath);
const idx = sprints.findIndex((s) => s.id === record.id);
if (idx >= 0) {
sprints[idx] = record;
} else {
sprints.unshift(record);
}
saveSprints(storagePath, sprints);
}
/** Find the most recent paused or executing sprint. */
export function findResumableSprint(storagePath: string): SprintRecord | null {
const sprints = loadSprints(storagePath);
return sprints.find((s) => s.status === "paused" || s.status === "executing") || null;
}