@agent-plan/core 0.2.20 → 0.2.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/display-status.d.ts +5 -3
- package/dist/display-status.d.ts.map +1 -1
- package/dist/display-status.js +14 -5
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/package-version.d.ts +9 -0
- package/dist/package-version.d.ts.map +1 -0
- package/dist/package-version.js +35 -0
- package/dist/plan-store.d.ts +7 -3
- package/dist/plan-store.d.ts.map +1 -1
- package/dist/plan-store.js +90 -8
- package/dist/recap.d.ts.map +1 -1
- package/dist/recap.js +63 -5
- package/dist/schema.d.ts +1107 -248
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +33 -7
- package/dist/task-selection.d.ts.map +1 -1
- package/dist/task-selection.js +30 -22
- package/package.json +1 -1
package/dist/display-status.d.ts
CHANGED
|
@@ -14,15 +14,15 @@
|
|
|
14
14
|
*
|
|
15
15
|
* These are NEVER persisted: they are computed on demand from children's
|
|
16
16
|
* canonical workflow statuses. The canonical workflow model
|
|
17
|
-
* (`planned | in-progress | waiting | blocked | deferred | done |
|
|
18
|
-
* rejected`)
|
|
17
|
+
* (`planned | in-progress | paused | waiting | blocked | deferred | done |
|
|
18
|
+
* canceled | rejected`) includes paused leaf work without implying active execution.
|
|
19
19
|
*/
|
|
20
20
|
import type { TaskStatus, PhaseStatus } from "./schema.js";
|
|
21
21
|
/**
|
|
22
22
|
* Canonical workflow status values used by tasks, phases, and features.
|
|
23
23
|
* Mirrors the union of TaskStatus and PhaseStatus used in the planner data.
|
|
24
24
|
*/
|
|
25
|
-
export type WorkflowStatus = "planned" | "in-progress" | "waiting" | "blocked" | "deferred" | "done" | "canceled" | "rejected";
|
|
25
|
+
export type WorkflowStatus = "planned" | "in-progress" | "paused" | "waiting" | "blocked" | "deferred" | "done" | "canceled" | "rejected";
|
|
26
26
|
/**
|
|
27
27
|
* Display status adds parent-only presentation states on top of workflow
|
|
28
28
|
* statuses. Only parent entities (feature, phase) use the full union; leaf
|
|
@@ -33,6 +33,7 @@ export type DisplayStatus = WorkflowStatus | "started" | "closed";
|
|
|
33
33
|
export interface StatusBreakdown {
|
|
34
34
|
planned: number;
|
|
35
35
|
inProgress: number;
|
|
36
|
+
paused: number;
|
|
36
37
|
waiting: number;
|
|
37
38
|
blocked: number;
|
|
38
39
|
deferred: number;
|
|
@@ -67,6 +68,7 @@ export declare function countBreakdown(statuses: readonly WorkflowStatus[]): Sta
|
|
|
67
68
|
* - all `rejected` → `rejected`
|
|
68
69
|
* - otherwise → `closed` (mixed terminal outcomes)
|
|
69
70
|
* 3. Compute `unfinished = meaningful ∩ OPEN`.
|
|
71
|
+
* - homogeneous `paused` → `paused`
|
|
70
72
|
* - homogeneous `waiting` → `waiting`
|
|
71
73
|
* - homogeneous `blocked` → `blocked`
|
|
72
74
|
* - homogeneous `deferred` → `deferred`
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"display-status.d.ts","sourceRoot":"","sources":["../src/display-status.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE3D;;;GAGG;AACH,MAAM,MAAM,cAAc,GACtB,SAAS,GACT,aAAa,GACb,SAAS,GACT,SAAS,GACT,UAAU,GACV,MAAM,GACN,UAAU,GACV,UAAU,CAAC;AAEf;;;;GAIG;AACH,MAAM,MAAM,aAAa,GAAG,cAAc,GAAG,SAAS,GAAG,QAAQ,CAAC;AAElE,+CAA+C;AAC/C,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,yDAAyD;AACzD,MAAM,WAAW,aAAa;IAC5B,uDAAuD;IACvD,aAAa,EAAE,aAAa,CAAC;IAC7B,wDAAwD;IACxD,SAAS,EAAE,eAAe,CAAC;IAC3B;+CAC2C;IAC3C,UAAU,EAAE,OAAO,CAAC;IACpB,8DAA8D;IAC9D,aAAa,EAAE,MAAM,CAAC;IACtB,8DAA8D;IAC9D,kBAAkB,EAAE,MAAM,CAAC;CAC5B;AAMD,iFAAiF;AACjF,wBAAgB,cAAc,CAAC,QAAQ,EAAE,SAAS,cAAc,EAAE,GAAG,eAAe,
|
|
1
|
+
{"version":3,"file":"display-status.d.ts","sourceRoot":"","sources":["../src/display-status.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE3D;;;GAGG;AACH,MAAM,MAAM,cAAc,GACtB,SAAS,GACT,aAAa,GACb,QAAQ,GACR,SAAS,GACT,SAAS,GACT,UAAU,GACV,MAAM,GACN,UAAU,GACV,UAAU,CAAC;AAEf;;;;GAIG;AACH,MAAM,MAAM,aAAa,GAAG,cAAc,GAAG,SAAS,GAAG,QAAQ,CAAC;AAElE,+CAA+C;AAC/C,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,yDAAyD;AACzD,MAAM,WAAW,aAAa;IAC5B,uDAAuD;IACvD,aAAa,EAAE,aAAa,CAAC;IAC7B,wDAAwD;IACxD,SAAS,EAAE,eAAe,CAAC;IAC3B;+CAC2C;IAC3C,UAAU,EAAE,OAAO,CAAC;IACpB,8DAA8D;IAC9D,aAAa,EAAE,MAAM,CAAC;IACtB,8DAA8D;IAC9D,kBAAkB,EAAE,MAAM,CAAC;CAC5B;AAMD,iFAAiF;AACjF,wBAAgB,cAAc,CAAC,QAAQ,EAAE,SAAS,cAAc,EAAE,GAAG,eAAe,CAmBnF;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,mBAAmB,CAAC,aAAa,EAAE,SAAS,cAAc,EAAE,GAAG,aAAa,CAsE3F;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI,CAerE;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,UAAU,GAAG,WAAW,GAAG,cAAc,CAIpF"}
|
package/dist/display-status.js
CHANGED
|
@@ -14,16 +14,16 @@
|
|
|
14
14
|
*
|
|
15
15
|
* These are NEVER persisted: they are computed on demand from children's
|
|
16
16
|
* canonical workflow statuses. The canonical workflow model
|
|
17
|
-
* (`planned | in-progress | waiting | blocked | deferred | done |
|
|
18
|
-
* rejected`)
|
|
17
|
+
* (`planned | in-progress | paused | waiting | blocked | deferred | done |
|
|
18
|
+
* canceled | rejected`) includes paused leaf work without implying active execution.
|
|
19
19
|
*/
|
|
20
20
|
const ACTIVE = new Set(["in-progress"]);
|
|
21
|
-
const OPEN = new Set(["planned", "waiting", "blocked", "deferred"]);
|
|
21
|
+
const OPEN = new Set(["planned", "paused", "waiting", "blocked", "deferred"]);
|
|
22
22
|
const TERMINAL = new Set(["done", "canceled", "rejected"]);
|
|
23
23
|
/** Count children per canonical workflow status. Pure; does not mutate input. */
|
|
24
24
|
export function countBreakdown(statuses) {
|
|
25
25
|
const breakdown = {
|
|
26
|
-
planned: 0, inProgress: 0, waiting: 0, blocked: 0,
|
|
26
|
+
planned: 0, inProgress: 0, paused: 0, waiting: 0, blocked: 0,
|
|
27
27
|
deferred: 0, done: 0, canceled: 0, rejected: 0,
|
|
28
28
|
};
|
|
29
29
|
for (const s of statuses) {
|
|
@@ -34,6 +34,9 @@ export function countBreakdown(statuses) {
|
|
|
34
34
|
case "in-progress":
|
|
35
35
|
breakdown.inProgress++;
|
|
36
36
|
break;
|
|
37
|
+
case "paused":
|
|
38
|
+
breakdown.paused++;
|
|
39
|
+
break;
|
|
37
40
|
case "waiting":
|
|
38
41
|
breakdown.waiting++;
|
|
39
42
|
break;
|
|
@@ -57,7 +60,7 @@ export function countBreakdown(statuses) {
|
|
|
57
60
|
return breakdown;
|
|
58
61
|
}
|
|
59
62
|
function emptyBreakdown() {
|
|
60
|
-
return { planned: 0, inProgress: 0, waiting: 0, blocked: 0, deferred: 0, done: 0, canceled: 0, rejected: 0 };
|
|
63
|
+
return { planned: 0, inProgress: 0, paused: 0, waiting: 0, blocked: 0, deferred: 0, done: 0, canceled: 0, rejected: 0 };
|
|
61
64
|
}
|
|
62
65
|
/**
|
|
63
66
|
* Derive the parent display snapshot from its children's canonical statuses.
|
|
@@ -70,6 +73,7 @@ function emptyBreakdown() {
|
|
|
70
73
|
* - all `rejected` → `rejected`
|
|
71
74
|
* - otherwise → `closed` (mixed terminal outcomes)
|
|
72
75
|
* 3. Compute `unfinished = meaningful ∩ OPEN`.
|
|
76
|
+
* - homogeneous `paused` → `paused`
|
|
73
77
|
* - homogeneous `waiting` → `waiting`
|
|
74
78
|
* - homogeneous `blocked` → `blocked`
|
|
75
79
|
* - homogeneous `deferred` → `deferred`
|
|
@@ -121,6 +125,10 @@ export function deriveParentDisplay(childStatuses) {
|
|
|
121
125
|
}
|
|
122
126
|
// 3. Unfinished meaningful remainder.
|
|
123
127
|
const unfinished = meaningful.filter((s) => OPEN.has(s));
|
|
128
|
+
const allPaused = unfinished.length > 0 && unfinished.every((s) => s === "paused");
|
|
129
|
+
if (allPaused) {
|
|
130
|
+
return { displayStatus: "paused", breakdown, hasStarted, totalChildren, meaningfulChildren };
|
|
131
|
+
}
|
|
124
132
|
const allWaiting = unfinished.length > 0 && unfinished.every((s) => s === "waiting");
|
|
125
133
|
if (allWaiting) {
|
|
126
134
|
return { displayStatus: "waiting", breakdown, hasStarted, totalChildren, meaningfulChildren };
|
|
@@ -150,6 +158,7 @@ export function toWorkflowStatus(value) {
|
|
|
150
158
|
switch (value) {
|
|
151
159
|
case "planned":
|
|
152
160
|
case "in-progress":
|
|
161
|
+
case "paused":
|
|
153
162
|
case "waiting":
|
|
154
163
|
case "blocked":
|
|
155
164
|
case "deferred":
|
package/dist/index.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ export * from "./recap.js";
|
|
|
6
6
|
export * from "./display-status.js";
|
|
7
7
|
export * from "./task-context.js";
|
|
8
8
|
export * from "./task-selection.js";
|
|
9
|
+
export * from "./package-version.js";
|
|
9
10
|
export { PlanStore, PlanStoreError, setWriteBusyHook, setWriteNotifyHook, migrateToUuids, migrateToGlobalSequence, withFeatureLock, type PhaseHandoffSummary, type OrphanPhaseSummary } from "./plan-store.js";
|
|
10
11
|
export { PlanRenderer } from "./renderer.js";
|
|
11
12
|
export { ExportService } from "./export-service.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC;AAC3B,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,cAAc,EAAE,uBAAuB,EAAE,eAAe,EAAE,KAAK,mBAAmB,EAAE,KAAK,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAC/M,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,YAAY,EAAE,eAAe,EAAE,WAAW,EAAE,aAAa,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC;AAC3B,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,cAAc,EAAE,uBAAuB,EAAE,eAAe,EAAE,KAAK,mBAAmB,EAAE,KAAK,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAC/M,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,YAAY,EAAE,eAAe,EAAE,WAAW,EAAE,aAAa,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -6,6 +6,7 @@ export * from "./recap.js";
|
|
|
6
6
|
export * from "./display-status.js";
|
|
7
7
|
export * from "./task-context.js";
|
|
8
8
|
export * from "./task-selection.js";
|
|
9
|
+
export * from "./package-version.js";
|
|
9
10
|
export { PlanStore, PlanStoreError, setWriteBusyHook, setWriteNotifyHook, migrateToUuids, migrateToGlobalSequence, withFeatureLock } from "./plan-store.js";
|
|
10
11
|
export { PlanRenderer } from "./renderer.js";
|
|
11
12
|
export { ExportService } from "./export-service.js";
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export interface RuntimePackageVersion {
|
|
2
|
+
name: string;
|
|
3
|
+
version: string;
|
|
4
|
+
}
|
|
5
|
+
/** Find the nearest matching package manifest above a loaded module. */
|
|
6
|
+
export declare function packageVersionFromModule(moduleUrlOrPath: string, expectedName: string): RuntimePackageVersion;
|
|
7
|
+
/** Resolve a dependency exactly as the caller loaded it, then read its manifest. */
|
|
8
|
+
export declare function resolvedPackageVersion(packageName: string, fromModuleUrl: string): RuntimePackageVersion;
|
|
9
|
+
//# sourceMappingURL=package-version.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"package-version.d.ts","sourceRoot":"","sources":["../src/package-version.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAaD,wEAAwE;AACxE,wBAAgB,wBAAwB,CACtC,eAAe,EAAE,MAAM,EACvB,YAAY,EAAE,MAAM,GACnB,qBAAqB,CAqBvB;AAED,oFAAoF;AACpF,wBAAgB,sBAAsB,CACpC,WAAW,EAAE,MAAM,EACnB,aAAa,EAAE,MAAM,GACpB,qBAAqB,CAGvB"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import { createRequire } from "node:module";
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
function modulePath(moduleUrlOrPath) {
|
|
6
|
+
return moduleUrlOrPath.startsWith("file:")
|
|
7
|
+
? fileURLToPath(moduleUrlOrPath)
|
|
8
|
+
: moduleUrlOrPath;
|
|
9
|
+
}
|
|
10
|
+
/** Find the nearest matching package manifest above a loaded module. */
|
|
11
|
+
export function packageVersionFromModule(moduleUrlOrPath, expectedName) {
|
|
12
|
+
let current = dirname(modulePath(moduleUrlOrPath));
|
|
13
|
+
while (true) {
|
|
14
|
+
const manifestPath = join(current, "package.json");
|
|
15
|
+
if (existsSync(manifestPath)) {
|
|
16
|
+
const manifest = JSON.parse(readFileSync(manifestPath, "utf-8"));
|
|
17
|
+
if (manifest.name === expectedName) {
|
|
18
|
+
if (typeof manifest.version !== "string" || !manifest.version.trim()) {
|
|
19
|
+
throw new Error(`Package ${expectedName} has no valid version in ${manifestPath}.`);
|
|
20
|
+
}
|
|
21
|
+
return { name: expectedName, version: manifest.version };
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
const parent = dirname(current);
|
|
25
|
+
if (parent === current)
|
|
26
|
+
break;
|
|
27
|
+
current = parent;
|
|
28
|
+
}
|
|
29
|
+
throw new Error(`Could not locate package.json for ${expectedName} from ${moduleUrlOrPath}.`);
|
|
30
|
+
}
|
|
31
|
+
/** Resolve a dependency exactly as the caller loaded it, then read its manifest. */
|
|
32
|
+
export function resolvedPackageVersion(packageName, fromModuleUrl) {
|
|
33
|
+
const entryPath = createRequire(fromModuleUrl).resolve(packageName);
|
|
34
|
+
return packageVersionFromModule(entryPath, packageName);
|
|
35
|
+
}
|
package/dist/plan-store.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import { type Feature, type FeaturesDocument, type Manifest, type Phase, type PlanWorkspace, type Project, type RequirementsDocument, type Requirement, type ActivityEntry, type ActivityLog, type CodebaseProfile, type ResumeFocus, type WorkDeviation } from "./schema.js";
|
|
2
|
+
import { type Feature, type FeaturesDocument, type Manifest, type Phase, type Task, type TaskPauseSnapshot, type PlanWorkspace, type Project, type RequirementsDocument, type Requirement, type ActivityEntry, type ActivityLog, type CodebaseProfile, type ResumeFocus, type WorkDeviation } from "./schema.js";
|
|
3
3
|
import { type ParentDisplay } from "./display-status.js";
|
|
4
4
|
export interface PlanStoreErrorDetails {
|
|
5
5
|
path?: string;
|
|
@@ -320,8 +320,8 @@ export declare class PlanStore {
|
|
|
320
320
|
updateProject(updater: (p: Project) => Project): Promise<Project>;
|
|
321
321
|
/** Persist an explicitly approved work deviation without coupling it to a harness. */
|
|
322
322
|
addWorkDeviation(deviation: WorkDeviation): Promise<Project>;
|
|
323
|
-
/**
|
|
324
|
-
setWorkDeviationState(id: string, state: "active" | "resolved" | "canceled", timestamp?: string): Promise<Project>;
|
|
323
|
+
/** Advance a deviation while retaining its complete audit and return stack. */
|
|
324
|
+
setWorkDeviationState(id: string, state: "active" | "resume-required" | "resolved" | "resumed" | "canceled", timestamp?: string): Promise<Project>;
|
|
325
325
|
updateFeatures(updater: (f: FeaturesDocument) => FeaturesDocument): Promise<FeaturesDocument>;
|
|
326
326
|
updateRequirements(updater: (r: RequirementsDocument) => RequirementsDocument): Promise<RequirementsDocument>;
|
|
327
327
|
saveProject(project: Project): Promise<void>;
|
|
@@ -336,6 +336,10 @@ export declare class PlanStore {
|
|
|
336
336
|
* task_create / phase_update calls on the SAME phaseId so batch operations
|
|
337
337
|
* don't lose tasks (last-write-wins race condition). */
|
|
338
338
|
updatePhase(phaseId: string, updater: (phase: Phase) => Phase): Promise<Phase>;
|
|
339
|
+
/** Pause active work with a mandatory durable checkpoint. */
|
|
340
|
+
pauseTask(phaseId: string, taskId: string, input: TaskPauseSnapshot): Promise<Task>;
|
|
341
|
+
/** Resume a paused task without resetting its original startedAt. */
|
|
342
|
+
resumeTask(phaseId: string, taskId: string, timestamp?: string): Promise<Task>;
|
|
339
343
|
/** Get the handoff text for a phase ("" if none). Throws if phase missing. */
|
|
340
344
|
getPhaseHandoff(phaseId: string): Promise<string>;
|
|
341
345
|
/** Set the handoff text for a phase + stamp handoffUpdatedAt. A completed or
|
package/dist/plan-store.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plan-store.d.ts","sourceRoot":"","sources":["../src/plan-store.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAY,MAAM,KAAK,CAAC;AAclC,OAAO,EAGL,KAAK,OAAO,EACZ,KAAK,gBAAgB,EAGrB,KAAK,QAAQ,EAEb,KAAK,KAAK,
|
|
1
|
+
{"version":3,"file":"plan-store.d.ts","sourceRoot":"","sources":["../src/plan-store.ts"],"names":[],"mappings":"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"}
|
package/dist/plan-store.js
CHANGED
|
@@ -14,7 +14,7 @@ const PLANNER_GITIGNORE = [
|
|
|
14
14
|
"generated/",
|
|
15
15
|
"",
|
|
16
16
|
].join("\n");
|
|
17
|
-
import { CodebaseProfileSchema, FeatureSchema, FeaturesDocumentSchema, ManifestSchema, PhaseSchema, ProjectSchema, RequirementsDocumentSchema, ResumeFocusSchema, ActivityLogSchema, TimestampSchema, } from "./schema.js";
|
|
17
|
+
import { CodebaseProfileSchema, FeatureSchema, FeaturesDocumentSchema, ManifestSchema, PhaseSchema, TaskPauseSnapshotSchema, ProjectSchema, RequirementsDocumentSchema, ResumeFocusSchema, ActivityLogSchema, TimestampSchema, } from "./schema.js";
|
|
18
18
|
import { createFeatureId, createPhaseId, createRequirementId, createShortId, createStatusLogEntryId, createTaskId, formatPhaseRef, isLegacyPhaseId } from "./naming.js";
|
|
19
19
|
import { deriveParentDisplay, fromCanonicalStatus } from "./display-status.js";
|
|
20
20
|
function nowISO() {
|
|
@@ -1592,27 +1592,32 @@ export class PlanStore {
|
|
|
1592
1592
|
return "done";
|
|
1593
1593
|
const hasDone = meaningful.some((s) => s === "done");
|
|
1594
1594
|
const hasActive = meaningful.some((s) => s === "in-progress");
|
|
1595
|
+
const hasPaused = meaningful.some((s) => s === "paused");
|
|
1595
1596
|
const hasPlanned = meaningful.some((s) => s === "planned");
|
|
1596
1597
|
const hasBlocked = meaningful.some((s) => s === "blocked");
|
|
1597
1598
|
const hasWaiting = meaningful.some((s) => s === "waiting");
|
|
1598
1599
|
const hasDeferred = meaningful.some((s) => s === "deferred");
|
|
1599
1600
|
if (hasActive)
|
|
1600
1601
|
return "in-progress";
|
|
1601
|
-
// If completed work exists and the ONLY remaining meaningful work is
|
|
1602
|
-
//
|
|
1603
|
-
if (hasDone && !hasPlanned && !hasBlocked && !hasWaiting && hasDeferred)
|
|
1602
|
+
// If completed work exists and the ONLY remaining meaningful work is paused
|
|
1603
|
+
// or deferred, do not imply active execution.
|
|
1604
|
+
if (hasDone && !hasPlanned && !hasBlocked && !hasWaiting && !hasDeferred && hasPaused)
|
|
1605
|
+
return "paused";
|
|
1606
|
+
if (hasDone && !hasPlanned && !hasBlocked && !hasWaiting && !hasPaused && hasDeferred)
|
|
1604
1607
|
return "deferred";
|
|
1605
1608
|
// Partial completion with remaining planned/blocked/waiting work still means
|
|
1606
1609
|
// the phase has genuinely started and is not terminal yet.
|
|
1607
1610
|
if (hasDone)
|
|
1608
1611
|
return "in-progress";
|
|
1609
|
-
// No progress at all ⇒ surface the stall / not-started state
|
|
1612
|
+
// No progress at all ⇒ surface the stall / not-started state.
|
|
1610
1613
|
if (hasBlocked)
|
|
1611
1614
|
return "blocked";
|
|
1612
1615
|
if (hasWaiting)
|
|
1613
1616
|
return "waiting";
|
|
1614
1617
|
if (hasDeferred)
|
|
1615
1618
|
return "deferred";
|
|
1619
|
+
if (hasPaused)
|
|
1620
|
+
return "paused";
|
|
1616
1621
|
return "planned";
|
|
1617
1622
|
}
|
|
1618
1623
|
deriveFeatureStatus(featureId, phases) {
|
|
@@ -1628,14 +1633,17 @@ export class PlanStore {
|
|
|
1628
1633
|
return "done";
|
|
1629
1634
|
const hasDone = meaningful.some((s) => s === "done");
|
|
1630
1635
|
const hasActive = meaningful.some((s) => s === "discovery" || s === "in-progress");
|
|
1636
|
+
const hasPaused = meaningful.some((s) => s === "paused");
|
|
1631
1637
|
const hasPlanned = meaningful.some((s) => s === "planned");
|
|
1632
1638
|
const hasBlocked = meaningful.some((s) => s === "blocked");
|
|
1633
1639
|
const hasWaiting = meaningful.some((s) => s === "waiting");
|
|
1634
1640
|
const hasDeferred = meaningful.some((s) => s === "deferred");
|
|
1635
1641
|
if (hasActive)
|
|
1636
1642
|
return "in-progress";
|
|
1637
|
-
// Same rule as phases: done + deferred-only remainder is
|
|
1638
|
-
if (hasDone && !hasPlanned && !hasBlocked && !hasWaiting && hasDeferred)
|
|
1643
|
+
// Same rule as phases: done + paused/deferred-only remainder is non-active.
|
|
1644
|
+
if (hasDone && !hasPlanned && !hasBlocked && !hasWaiting && !hasDeferred && hasPaused)
|
|
1645
|
+
return "paused";
|
|
1646
|
+
if (hasDone && !hasPlanned && !hasBlocked && !hasWaiting && !hasPaused && hasDeferred)
|
|
1639
1647
|
return "deferred";
|
|
1640
1648
|
if (hasDone)
|
|
1641
1649
|
return "in-progress";
|
|
@@ -1646,6 +1654,8 @@ export class PlanStore {
|
|
|
1646
1654
|
return "waiting";
|
|
1647
1655
|
if (hasDeferred)
|
|
1648
1656
|
return "deferred";
|
|
1657
|
+
if (hasPaused)
|
|
1658
|
+
return "paused";
|
|
1649
1659
|
return "planned";
|
|
1650
1660
|
}
|
|
1651
1661
|
async syncStatuses() {
|
|
@@ -1735,7 +1745,7 @@ export class PlanStore {
|
|
|
1735
1745
|
workDeviations: [...project.workDeviations, deviation],
|
|
1736
1746
|
}));
|
|
1737
1747
|
}
|
|
1738
|
-
/**
|
|
1748
|
+
/** Advance a deviation while retaining its complete audit and return stack. */
|
|
1739
1749
|
async setWorkDeviationState(id, state, timestamp = nowISO()) {
|
|
1740
1750
|
return this.updateProject((project) => ({
|
|
1741
1751
|
...project,
|
|
@@ -1743,7 +1753,9 @@ export class PlanStore {
|
|
|
1743
1753
|
...deviation,
|
|
1744
1754
|
state,
|
|
1745
1755
|
activatedAt: state === "active" ? timestamp : deviation.activatedAt,
|
|
1756
|
+
resumeRequiredAt: state === "resume-required" ? timestamp : deviation.resumeRequiredAt,
|
|
1746
1757
|
resolvedAt: state === "resolved" || state === "canceled" ? timestamp : deviation.resolvedAt,
|
|
1758
|
+
resumedAt: state === "resumed" ? timestamp : deviation.resumedAt,
|
|
1747
1759
|
}),
|
|
1748
1760
|
}));
|
|
1749
1761
|
}
|
|
@@ -1888,6 +1900,76 @@ export class PlanStore {
|
|
|
1888
1900
|
await this.maybeAutoSync();
|
|
1889
1901
|
return { ...raw, status: this.derivePhaseStatus(raw.tasks) };
|
|
1890
1902
|
}
|
|
1903
|
+
/** Pause active work with a mandatory durable checkpoint. */
|
|
1904
|
+
async pauseTask(phaseId, taskId, input) {
|
|
1905
|
+
const snapshot = TaskPauseSnapshotSchema.parse(input);
|
|
1906
|
+
let paused;
|
|
1907
|
+
await this.updatePhase(phaseId, (phase) => {
|
|
1908
|
+
const task = phase.tasks.find((candidate) => candidate.id === taskId);
|
|
1909
|
+
if (!task)
|
|
1910
|
+
throw new PlanStoreError(`Task ${taskId} does not belong to phase ${phaseId}.`);
|
|
1911
|
+
if (task.status !== "in-progress") {
|
|
1912
|
+
throw new PlanStoreError(`Task ${taskId} cannot be paused from ${task.status}; only in-progress work can be paused.`);
|
|
1913
|
+
}
|
|
1914
|
+
const description = [
|
|
1915
|
+
`Reason: ${snapshot.reason}`,
|
|
1916
|
+
`What was being done: ${snapshot.whatWasBeingDone}`,
|
|
1917
|
+
`Resume location: ${snapshot.resumeLocation}`,
|
|
1918
|
+
`How to resume: ${snapshot.howToResume}`,
|
|
1919
|
+
].join("\n");
|
|
1920
|
+
paused = {
|
|
1921
|
+
...task,
|
|
1922
|
+
status: "paused",
|
|
1923
|
+
pauseSnapshot: snapshot,
|
|
1924
|
+
pauseHistory: [...task.pauseHistory, snapshot],
|
|
1925
|
+
statusLog: [...task.statusLog, {
|
|
1926
|
+
id: createStatusLogEntryId(),
|
|
1927
|
+
date: snapshot.pausedAt,
|
|
1928
|
+
fromStatus: "in-progress",
|
|
1929
|
+
toStatus: "paused",
|
|
1930
|
+
title: "in-progress → paused",
|
|
1931
|
+
description,
|
|
1932
|
+
}],
|
|
1933
|
+
updatedAt: snapshot.pausedAt,
|
|
1934
|
+
};
|
|
1935
|
+
phase.tasks = phase.tasks.map((candidate) => candidate.id === taskId ? paused : candidate);
|
|
1936
|
+
return phase;
|
|
1937
|
+
});
|
|
1938
|
+
return paused;
|
|
1939
|
+
}
|
|
1940
|
+
/** Resume a paused task without resetting its original startedAt. */
|
|
1941
|
+
async resumeTask(phaseId, taskId, timestamp = nowISO()) {
|
|
1942
|
+
let resumed;
|
|
1943
|
+
await this.updatePhase(phaseId, (phase) => {
|
|
1944
|
+
const task = phase.tasks.find((candidate) => candidate.id === taskId);
|
|
1945
|
+
if (!task)
|
|
1946
|
+
throw new PlanStoreError(`Task ${taskId} does not belong to phase ${phaseId}.`);
|
|
1947
|
+
if (task.status !== "paused") {
|
|
1948
|
+
throw new PlanStoreError(`Task ${taskId} cannot be resumed from ${task.status}; only paused work can be resumed.`);
|
|
1949
|
+
}
|
|
1950
|
+
const snapshot = task.pauseSnapshot;
|
|
1951
|
+
resumed = {
|
|
1952
|
+
...task,
|
|
1953
|
+
status: "in-progress",
|
|
1954
|
+
pauseSnapshot: null,
|
|
1955
|
+
startedAt: task.startedAt || timestamp,
|
|
1956
|
+
statusLog: [...task.statusLog, {
|
|
1957
|
+
id: createStatusLogEntryId(),
|
|
1958
|
+
date: timestamp,
|
|
1959
|
+
fromStatus: "paused",
|
|
1960
|
+
toStatus: "in-progress",
|
|
1961
|
+
title: "paused → in-progress",
|
|
1962
|
+
description: snapshot
|
|
1963
|
+
? `Resumed from ${snapshot.resumeLocation}. ${snapshot.howToResume}`
|
|
1964
|
+
: "Paused task resumed.",
|
|
1965
|
+
}],
|
|
1966
|
+
updatedAt: timestamp,
|
|
1967
|
+
};
|
|
1968
|
+
phase.tasks = phase.tasks.map((candidate) => candidate.id === taskId ? resumed : candidate);
|
|
1969
|
+
return phase;
|
|
1970
|
+
});
|
|
1971
|
+
return resumed;
|
|
1972
|
+
}
|
|
1891
1973
|
// ── Phase-scoped handoff (entity field, harness-agnostic) ────────────
|
|
1892
1974
|
/** Get the handoff text for a phase ("" if none). Throws if phase missing. */
|
|
1893
1975
|
async getPhaseHandoff(phaseId) {
|
package/dist/recap.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"recap.d.ts","sourceRoot":"","sources":["../src/recap.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAGjD;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC3B;AAED,yEAAyE;AACzE,MAAM,MAAM,YAAY,GAAG,IAAI,GAAG,KAAK,CAAC;AAExC,MAAM,WAAW,YAAY;IAC3B,OAAO,CAAC,EAAE,YAAY,CAAC;CACxB;AAKD;;;;;;;;;;;;;GAaG;AACH,wBAAsB,UAAU,CAAC,EAAE,EAAE,SAAS,EAAE,GAAG,GAAE,YAAiB,EAAE,IAAI,GAAE,YAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,
|
|
1
|
+
{"version":3,"file":"recap.d.ts","sourceRoot":"","sources":["../src/recap.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAGjD;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC3B;AAED,yEAAyE;AACzE,MAAM,MAAM,YAAY,GAAG,IAAI,GAAG,KAAK,CAAC;AAExC,MAAM,WAAW,YAAY;IAC3B,OAAO,CAAC,EAAE,YAAY,CAAC;CACxB;AAKD;;;;;;;;;;;;;GAaG;AACH,wBAAsB,UAAU,CAAC,EAAE,EAAE,SAAS,EAAE,GAAG,GAAE,YAAiB,EAAE,IAAI,GAAE,YAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,CAmOhH"}
|
package/dist/recap.js
CHANGED
|
@@ -33,6 +33,20 @@ export async function buildRecap(st, web = {}, opts = {}) {
|
|
|
33
33
|
const totalT = allTasks.length;
|
|
34
34
|
const doneT = allTasks.filter(({ task }) => task.status === "done").length;
|
|
35
35
|
const activeT = allTasks.filter(({ task }) => task.status === "in-progress").length;
|
|
36
|
+
const pausedTasks = allTasks.filter(({ task }) => task.status === "paused");
|
|
37
|
+
const pausedT = pausedTasks.length;
|
|
38
|
+
const pendingDeviation = [...plan.project.workDeviations]
|
|
39
|
+
.filter((deviation) => deviation.state === "resume-required" || deviation.state === "resolved")
|
|
40
|
+
.sort((left, right) => right.createdAt.localeCompare(left.createdAt))
|
|
41
|
+
.find((deviation) => allTasks.some(({ task }) => task.id === deviation.resumeTaskId
|
|
42
|
+
&& (task.status === "paused" || task.status === "planned" || task.status === "waiting")));
|
|
43
|
+
const pendingResume = pendingDeviation
|
|
44
|
+
? allTasks.find(({ task }) => task.id === pendingDeviation.resumeTaskId)
|
|
45
|
+
: undefined;
|
|
46
|
+
const standalonePaused = pausedTasks
|
|
47
|
+
.filter(({ task }) => task.id !== pendingResume?.task.id)
|
|
48
|
+
.sort((left, right) => (right.task.pauseSnapshot?.pausedAt ?? "").localeCompare(left.task.pauseSnapshot?.pausedAt ?? ""));
|
|
49
|
+
const latestStandalonePaused = standalonePaused[0];
|
|
36
50
|
// Plan is fully complete: there is work and all of it is done, nothing active.
|
|
37
51
|
// (totalT > 0 guards the empty/unstarted case from looking "complete".)
|
|
38
52
|
const planComplete = totalT > 0 && doneT === totalT && doneP === totalP && doneF === totalF;
|
|
@@ -54,14 +68,24 @@ export async function buildRecap(st, web = {}, opts = {}) {
|
|
|
54
68
|
const name = plan.project.name || "(unnamed project)";
|
|
55
69
|
lines.push(`${italian ? "Progetto" : "Project"}: ${name}${plan.project.goal ? " — " + plan.project.goal : ""}`);
|
|
56
70
|
lines.push(italian
|
|
57
|
-
? `Avanzamento: feature ${doneF}/${totalF} completate (${activeF} attive) · fasi ${doneP}/${totalP} completate (${activeP} attive) · task ${doneT}/${totalT} completati (${activeT} attivi)`
|
|
58
|
-
: `Progress: Features ${doneF}/${totalF} done (${activeF} active) · Phases ${doneP}/${totalP} done (${activeP} active) · Tasks ${doneT}/${totalT} done (${activeT} active)`);
|
|
71
|
+
? `Avanzamento: feature ${doneF}/${totalF} completate (${activeF} attive) · fasi ${doneP}/${totalP} completate (${activeP} attive) · task ${doneT}/${totalT} completati (${activeT} attivi, ${pausedT} in pausa)`
|
|
72
|
+
: `Progress: Features ${doneF}/${totalF} done (${activeF} active) · Phases ${doneP}/${totalP} done (${activeP} active) · Tasks ${doneT}/${totalT} done (${activeT} active, ${pausedT} paused)`);
|
|
59
73
|
if (focusTask && focusPhase) {
|
|
60
74
|
const fr = focusFeature ? fref(focusFeature.number) : "?";
|
|
61
75
|
const pr = formatPhaseRef(focusPhase.number, focusFeature?.number);
|
|
62
76
|
const tr = tref(focusTask.task.number);
|
|
63
77
|
lines.push(`${italian ? "Focus corrente" : "Current focus"}: ${fr} — ${focusFeature?.name ?? "?"} / ${pr} — ${focusPhase.title} / ${tr} — ${focusTask.task.title} (in-progress)`);
|
|
64
78
|
}
|
|
79
|
+
else if (pendingResume) {
|
|
80
|
+
const feature = feats.find((entry) => entry.id === pendingResume.phase.featureId);
|
|
81
|
+
const ref = `${formatPhaseRef(pendingResume.phase.number, feature?.number)}/${tref(pendingResume.task.number)}`;
|
|
82
|
+
lines.push(`${italian ? "Focus corrente" : "Current focus"}: ${italian ? "ripresa obbligatoria" : "resume required"} — ${ref} — ${pendingResume.task.title} (${pendingResume.task.status})`);
|
|
83
|
+
}
|
|
84
|
+
else if (latestStandalonePaused) {
|
|
85
|
+
const feature = feats.find((entry) => entry.id === latestStandalonePaused.phase.featureId);
|
|
86
|
+
const ref = `${formatPhaseRef(latestStandalonePaused.phase.number, feature?.number)}/${tref(latestStandalonePaused.task.number)}`;
|
|
87
|
+
lines.push(`${italian ? "Focus corrente" : "Current focus"}: ${italian ? "task in pausa da riprendere" : "paused task to resume"} — ${ref} — ${latestStandalonePaused.task.title}`);
|
|
88
|
+
}
|
|
65
89
|
else if (handoffs.length > 0) {
|
|
66
90
|
const top = handoffs[0];
|
|
67
91
|
lines.push(`${italian ? "Focus corrente" : "Current focus"}: ${italian ? "nessun task attivo" : "no active task"} · ${italian ? "handoff pendente più recente" : "most recent pending handoff"}: ${top.compositeRef} — "${top.firstLine}"`);
|
|
@@ -79,7 +103,21 @@ export async function buildRecap(st, web = {}, opts = {}) {
|
|
|
79
103
|
// instead of surfacing potentially-stale resume.json nextSteps. When no
|
|
80
104
|
// handoff exists, fall back to resume.nextSteps but mark them as possibly
|
|
81
105
|
// stale (free-text that refreshResume never touches, so they can drift).
|
|
82
|
-
if (
|
|
106
|
+
if (pendingResume) {
|
|
107
|
+
const feature = feats.find((entry) => entry.id === pendingResume.phase.featureId);
|
|
108
|
+
const ref = `${formatPhaseRef(pendingResume.phase.number, feature?.number)}/${tref(pendingResume.task.number)}`;
|
|
109
|
+
lines.push(italian
|
|
110
|
+
? `Prossimo step: riprendi ${ref} con ${taskStartCmd}. Il checkpoint del task è prioritario rispetto a nuovo lavoro e handoff di fase.`
|
|
111
|
+
: `Next step: resume ${ref} with ${taskStartCmd}. Its task checkpoint takes precedence over new work and phase handoffs.`);
|
|
112
|
+
}
|
|
113
|
+
else if (latestStandalonePaused) {
|
|
114
|
+
const feature = feats.find((entry) => entry.id === latestStandalonePaused.phase.featureId);
|
|
115
|
+
const ref = `${formatPhaseRef(latestStandalonePaused.phase.number, feature?.number)}/${tref(latestStandalonePaused.task.number)}`;
|
|
116
|
+
lines.push(italian
|
|
117
|
+
? `Prossimo step: riprendi il checkpoint più recente, ${ref}, con ${taskStartCmd}, prima di scegliere nuovo lavoro.`
|
|
118
|
+
: `Next step: resume the newest checkpoint, ${ref}, with ${taskStartCmd} before selecting new work.`);
|
|
119
|
+
}
|
|
120
|
+
else if (handoffs.length > 0) {
|
|
83
121
|
lines.push(italian
|
|
84
122
|
? `Prossimo step: leggi l'handoff di fase pendente sotto (fonte autorevole, gestita attivamente). I nextSteps legacy di resume.json sono soppressi perché possono essere stale.`
|
|
85
123
|
: `Next step: read the pending phase handoff below (authoritative, actively maintained). Legacy resume.json nextSteps are suppressed because they may be stale.`);
|
|
@@ -95,11 +133,31 @@ export async function buildRecap(st, web = {}, opts = {}) {
|
|
|
95
133
|
: `⚠️ nextSteps are free-text from resume.json — may be stale; verify against current state before acting.`);
|
|
96
134
|
lines.push(staleNote);
|
|
97
135
|
}
|
|
136
|
+
if (pendingResume) {
|
|
137
|
+
const feature = feats.find((entry) => entry.id === pendingResume.phase.featureId);
|
|
138
|
+
const ref = `${formatPhaseRef(pendingResume.phase.number, feature?.number)}/${tref(pendingResume.task.number)}`;
|
|
139
|
+
const snapshot = pendingResume.task.pauseSnapshot ?? pendingDeviation?.snapshot;
|
|
140
|
+
lines.push("", italian ? "## Ripresa task obbligatoria" : "## Task resume required", `${ref} — ${pendingResume.task.title}`, snapshot ? `${italian ? "Perché è stato sospeso" : "Paused because"}: ${snapshot.reason}` : "", snapshot ? `${italian ? "Stato del lavoro" : "Work checkpoint"}: ${snapshot.whatWasBeingDone}` : "", snapshot ? `${italian ? "Riprendi da" : "Resume from"}: ${snapshot.resumeLocation}` : "", snapshot ? `${italian ? "Come riprendere" : "How to resume"}: ${snapshot.howToResume}` : "", `${italian ? "Azione" : "Action"}: ${taskStartCmd} ${ref}`);
|
|
141
|
+
}
|
|
142
|
+
if (standalonePaused.length > 0) {
|
|
143
|
+
lines.push("", italian ? `## Task in pausa (${standalonePaused.length})` : `## Paused tasks (${standalonePaused.length})`);
|
|
144
|
+
for (const entry of standalonePaused) {
|
|
145
|
+
const feature = feats.find((item) => item.id === entry.phase.featureId);
|
|
146
|
+
const ref = `${formatPhaseRef(entry.phase.number, feature?.number)}/${tref(entry.task.number)}`;
|
|
147
|
+
const snapshot = entry.task.pauseSnapshot;
|
|
148
|
+
lines.push(`${ref} — ${entry.task.title}`, snapshot ? ` ${italian ? "Perché" : "Why"}: ${snapshot.reason}` : "", snapshot ? ` ${italian ? "Stato" : "Checkpoint"}: ${snapshot.whatWasBeingDone}` : "", snapshot ? ` ${italian ? "Riprendi da" : "Resume from"}: ${snapshot.resumeLocation}` : "", snapshot ? ` ${italian ? "Come" : "How"}: ${snapshot.howToResume}` : "");
|
|
149
|
+
}
|
|
150
|
+
}
|
|
98
151
|
if (handoffs.length > 0) {
|
|
99
152
|
const top = handoffs[0];
|
|
100
153
|
lines.push("", italian ? `## Handoff di fase pendenti (${handoffs.length})` : `## Pending phase handoffs (${handoffs.length})`);
|
|
101
154
|
handoffs.forEach((h, i) => lines.push(`[${i + 1}] ${h.compositeRef} — ${h.updatedAt} — "${h.firstLine}"`));
|
|
102
|
-
if (
|
|
155
|
+
if (pendingResume || latestStandalonePaused) {
|
|
156
|
+
lines.push("", italian
|
|
157
|
+
? "→ Questi handoff restano disponibili come contesto, ma prima risolvi il task da riprendere indicato sopra."
|
|
158
|
+
: "→ These handoffs remain available as context, but first resolve the task resume shown above.");
|
|
159
|
+
}
|
|
160
|
+
else if (handoffs.length === 1) {
|
|
103
161
|
lines.push("", italian
|
|
104
162
|
? `→ Vuoi riprendere da ${top.compositeRef}? Leggi l'handoff con ${handoffShowCmd} ${top.compositeRef} e avvia il primo task pertinente. L'handoff resta attivo finché tutti i task della fase non sono done/canceled, viene sostituito da un nuovo handoff, oppure viene cancellato esplicitamente.`
|
|
105
163
|
: `→ Do you want to resume from ${top.compositeRef}? Read the handoff with ${handoffShowCmd} ${top.compositeRef} and start the first relevant task. It stays active until every phase task is done/canceled, a new handoff replaces it, or it is explicitly cleared.`);
|
|
@@ -115,7 +173,7 @@ export async function buildRecap(st, web = {}, opts = {}) {
|
|
|
115
173
|
? `Piano completo — aggiungi una nuova feature (${featureAddCmd}) o fase (${phaseAddCmd}) per continuare.`
|
|
116
174
|
: `Plan complete — add a new feature (${featureAddCmd}) or phase (${phaseAddCmd}) to continue.`);
|
|
117
175
|
}
|
|
118
|
-
else if (activeT === 0) {
|
|
176
|
+
else if (activeT === 0 && !pendingResume && standalonePaused.length === 0) {
|
|
119
177
|
lines.push("", italian
|
|
120
178
|
? `Nessun handoff pendente e nessun task in-progress. Usa ${taskAddCmd} / ${taskStartCmd} per iniziare.`
|
|
121
179
|
: `No phase handoff pending and no task in-progress. Use ${taskAddCmd} / ${taskStartCmd} to begin work.`);
|