@agent-plan/core 0.2.19-next.1 → 0.2.19-next.10
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/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/plan-store.d.ts +80 -12
- package/dist/plan-store.d.ts.map +1 -1
- package/dist/plan-store.js +277 -92
- package/dist/recap.d.ts.map +1 -1
- package/dist/recap.js +21 -7
- package/dist/refs.d.ts +23 -0
- package/dist/refs.d.ts.map +1 -1
- package/dist/refs.js +66 -0
- package/dist/schema.d.ts +139 -0
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +28 -0
- package/package.json +1 -1
package/dist/refs.js
CHANGED
|
@@ -40,3 +40,69 @@ export function findPhaseByRef(phases, features, ref) {
|
|
|
40
40
|
return (phases.find((p) => p.title.toLowerCase() === normalized) ??
|
|
41
41
|
phases.find((p) => p.title.toLowerCase().includes(normalized)));
|
|
42
42
|
}
|
|
43
|
+
// Extract optional feature/phase/task numbers from a composite ref.
|
|
44
|
+
// Accepts 1+ digits so "t3" == "t003". Numbers are GLOBAL (post-migration).
|
|
45
|
+
function parseTaskComposite(ref) {
|
|
46
|
+
const t = ref.match(/t0*(\d+)/);
|
|
47
|
+
const p = ref.match(/p0*(\d+)/);
|
|
48
|
+
const f = ref.match(/f0*(\d+)/);
|
|
49
|
+
return {
|
|
50
|
+
taskNum: t ? parseInt(t[1], 10) : undefined,
|
|
51
|
+
phaseNum: p ? parseInt(p[1], 10) : undefined,
|
|
52
|
+
featureNum: f ? parseInt(f[1], 10) : undefined,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
export function findTaskByRef(phases, features, ref) {
|
|
56
|
+
const normalized = ref.trim().toLowerCase();
|
|
57
|
+
if (!normalized)
|
|
58
|
+
return undefined;
|
|
59
|
+
// 1. UUID (exact)
|
|
60
|
+
for (const phase of phases) {
|
|
61
|
+
const task = phase.tasks.find((t) => t.id.toLowerCase() === normalized);
|
|
62
|
+
if (task)
|
|
63
|
+
return { phase, task };
|
|
64
|
+
}
|
|
65
|
+
// 2. Composite / short ref with a T segment
|
|
66
|
+
const { featureNum, phaseNum, taskNum } = parseTaskComposite(normalized);
|
|
67
|
+
if (taskNum !== undefined) {
|
|
68
|
+
if (phaseNum !== undefined) {
|
|
69
|
+
// Composite: validate phase (and feature if present), then resolve task by number.
|
|
70
|
+
const phase = phases.find((p) => p.number === phaseNum);
|
|
71
|
+
if (!phase)
|
|
72
|
+
return undefined;
|
|
73
|
+
if (featureNum !== undefined) {
|
|
74
|
+
const feat = features.find((f) => f.number === featureNum);
|
|
75
|
+
if (!feat || phase.featureId !== feat.id)
|
|
76
|
+
return undefined;
|
|
77
|
+
}
|
|
78
|
+
const task = phase.tasks.find((t) => t.number === taskNum);
|
|
79
|
+
if (task)
|
|
80
|
+
return { phase, task };
|
|
81
|
+
return undefined;
|
|
82
|
+
}
|
|
83
|
+
// Bare T00x — globally unique under the new numbering. Find the one task.
|
|
84
|
+
for (const phase of phases) {
|
|
85
|
+
const task = phase.tasks.find((t) => t.number === taskNum);
|
|
86
|
+
if (task)
|
|
87
|
+
return { phase, task };
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
// 3. ShortId (5-char)
|
|
91
|
+
for (const phase of phases) {
|
|
92
|
+
const task = phase.tasks.find((t) => t.shortId && t.shortId.toLowerCase() === normalized);
|
|
93
|
+
if (task)
|
|
94
|
+
return { phase, task };
|
|
95
|
+
}
|
|
96
|
+
// 4. Title fallback (backward compatibility)
|
|
97
|
+
for (const phase of phases) {
|
|
98
|
+
const exact = phase.tasks.find((t) => t.title.toLowerCase() === normalized);
|
|
99
|
+
if (exact)
|
|
100
|
+
return { phase, task: exact };
|
|
101
|
+
}
|
|
102
|
+
for (const phase of phases) {
|
|
103
|
+
const incl = phase.tasks.find((t) => t.title.toLowerCase().includes(normalized));
|
|
104
|
+
if (incl)
|
|
105
|
+
return { phase, task: incl };
|
|
106
|
+
}
|
|
107
|
+
return undefined;
|
|
108
|
+
}
|
package/dist/schema.d.ts
CHANGED
|
@@ -133,6 +133,10 @@ export declare const ResumeFocusSchema: z.ZodObject<{
|
|
|
133
133
|
currentPhaseId: z.ZodDefault<z.ZodString>;
|
|
134
134
|
inProgressTaskIds: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
135
135
|
nextSteps: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
136
|
+
/** When `nextSteps` last changed (free-text can go stale; the recap surfaces
|
|
137
|
+
* this so staleness is visible). Preserved across refreshResume (which keeps
|
|
138
|
+
* existing nextSteps); bumped only when saveResume receives new nextSteps. */
|
|
139
|
+
nextStepsUpdatedAt: z.ZodDefault<z.ZodString>;
|
|
136
140
|
blockers: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
137
141
|
notes: z.ZodDefault<z.ZodString>;
|
|
138
142
|
lastSessionSummary: z.ZodDefault<z.ZodString>;
|
|
@@ -142,6 +146,7 @@ export declare const ResumeFocusSchema: z.ZodObject<{
|
|
|
142
146
|
currentPhaseId: string;
|
|
143
147
|
inProgressTaskIds: string[];
|
|
144
148
|
nextSteps: string[];
|
|
149
|
+
nextStepsUpdatedAt: string;
|
|
145
150
|
blockers: string[];
|
|
146
151
|
notes: string;
|
|
147
152
|
lastSessionSummary: string;
|
|
@@ -151,6 +156,7 @@ export declare const ResumeFocusSchema: z.ZodObject<{
|
|
|
151
156
|
currentPhaseId?: string | undefined;
|
|
152
157
|
inProgressTaskIds?: string[] | undefined;
|
|
153
158
|
nextSteps?: string[] | undefined;
|
|
159
|
+
nextStepsUpdatedAt?: string | undefined;
|
|
154
160
|
blockers?: string[] | undefined;
|
|
155
161
|
notes?: string | undefined;
|
|
156
162
|
lastSessionSummary?: string | undefined;
|
|
@@ -314,6 +320,10 @@ export declare const ProjectSchema: z.ZodObject<{
|
|
|
314
320
|
rationale?: string | undefined;
|
|
315
321
|
implementationNotes?: string | undefined;
|
|
316
322
|
}>, "many">>;
|
|
323
|
+
/** Monotonic global sequence counters — assigned at creation, never reused (gaps on delete). */
|
|
324
|
+
nextFeatureNumber: z.ZodDefault<z.ZodNumber>;
|
|
325
|
+
nextPhaseNumber: z.ZodDefault<z.ZodNumber>;
|
|
326
|
+
nextTaskNumber: z.ZodDefault<z.ZodNumber>;
|
|
317
327
|
}, "strip", z.ZodTypeAny, {
|
|
318
328
|
name: string;
|
|
319
329
|
goal: string;
|
|
@@ -340,6 +350,9 @@ export declare const ProjectSchema: z.ZodObject<{
|
|
|
340
350
|
implementationNotes: string;
|
|
341
351
|
acceptedAt: string;
|
|
342
352
|
}[];
|
|
353
|
+
nextFeatureNumber: number;
|
|
354
|
+
nextPhaseNumber: number;
|
|
355
|
+
nextTaskNumber: number;
|
|
343
356
|
}, {
|
|
344
357
|
name: string;
|
|
345
358
|
workflowRules: {
|
|
@@ -366,6 +379,9 @@ export declare const ProjectSchema: z.ZodObject<{
|
|
|
366
379
|
rationale?: string | undefined;
|
|
367
380
|
implementationNotes?: string | undefined;
|
|
368
381
|
}[] | undefined;
|
|
382
|
+
nextFeatureNumber?: number | undefined;
|
|
383
|
+
nextPhaseNumber?: number | undefined;
|
|
384
|
+
nextTaskNumber?: number | undefined;
|
|
369
385
|
}>;
|
|
370
386
|
export declare const SubtaskStatusSchema: z.ZodEnum<["planned", "in-progress", "done", "blocked", "canceled", "rejected", "deferred", "waiting"]>;
|
|
371
387
|
export declare const TaskStatusSchema: z.ZodEnum<["planned", "in-progress", "done", "blocked", "canceled", "rejected", "deferred", "waiting"]>;
|
|
@@ -441,6 +457,7 @@ export declare const StatusLogEntrySchema: z.ZodObject<{
|
|
|
441
457
|
export declare const TaskSchema: z.ZodEffects<z.ZodObject<{
|
|
442
458
|
id: z.ZodString;
|
|
443
459
|
phaseId: z.ZodString;
|
|
460
|
+
/** Global project-wide task sequence (assigned once at creation from project.nextTaskNumber; stable, gaps on delete). Bare T00x is unambiguous. */
|
|
444
461
|
number: z.ZodDefault<z.ZodNumber>;
|
|
445
462
|
shortId: z.ZodDefault<z.ZodString>;
|
|
446
463
|
priority: z.ZodDefault<z.ZodNumber>;
|
|
@@ -719,9 +736,25 @@ export declare const TaskSchema: z.ZodEffects<z.ZodObject<{
|
|
|
719
736
|
startedAt?: string | undefined;
|
|
720
737
|
completedAt?: string | undefined;
|
|
721
738
|
}>;
|
|
739
|
+
export declare const HandoffHistoryEntrySchema: z.ZodObject<{
|
|
740
|
+
/** Relative path under .planner/handoff-archive/ (e.g. <phaseId>-<ISO>.md). */
|
|
741
|
+
file: z.ZodDefault<z.ZodString>;
|
|
742
|
+
clearedAt: z.ZodString;
|
|
743
|
+
/** Why the handoff was cleared: "task-started" | "phase-done" | "manual" | "superseded" | "imported". */
|
|
744
|
+
reason: z.ZodDefault<z.ZodString>;
|
|
745
|
+
}, "strip", z.ZodTypeAny, {
|
|
746
|
+
file: string;
|
|
747
|
+
clearedAt: string;
|
|
748
|
+
reason: string;
|
|
749
|
+
}, {
|
|
750
|
+
clearedAt: string;
|
|
751
|
+
file?: string | undefined;
|
|
752
|
+
reason?: string | undefined;
|
|
753
|
+
}>;
|
|
722
754
|
export declare const PhaseSchema: z.ZodObject<{
|
|
723
755
|
id: z.ZodString;
|
|
724
756
|
featureId: z.ZodOptional<z.ZodString>;
|
|
757
|
+
/** Global project-wide phase sequence (assigned once at creation from project.nextPhaseNumber; stable, gaps on delete). Bare P00x is unambiguous. */
|
|
725
758
|
number: z.ZodNumber;
|
|
726
759
|
shortId: z.ZodDefault<z.ZodString>;
|
|
727
760
|
priority: z.ZodDefault<z.ZodNumber>;
|
|
@@ -767,6 +800,7 @@ export declare const PhaseSchema: z.ZodObject<{
|
|
|
767
800
|
tasks: z.ZodDefault<z.ZodArray<z.ZodEffects<z.ZodObject<{
|
|
768
801
|
id: z.ZodString;
|
|
769
802
|
phaseId: z.ZodString;
|
|
803
|
+
/** Global project-wide task sequence (assigned once at creation from project.nextTaskNumber; stable, gaps on delete). Bare T00x is unambiguous. */
|
|
770
804
|
number: z.ZodDefault<z.ZodNumber>;
|
|
771
805
|
shortId: z.ZodDefault<z.ZodString>;
|
|
772
806
|
priority: z.ZodDefault<z.ZodNumber>;
|
|
@@ -1049,6 +1083,30 @@ export declare const PhaseSchema: z.ZodObject<{
|
|
|
1049
1083
|
updatedAt: z.ZodString;
|
|
1050
1084
|
handoff: z.ZodDefault<z.ZodString>;
|
|
1051
1085
|
handoffUpdatedAt: z.ZodDefault<z.ZodString>;
|
|
1086
|
+
/** When the handoff was last read/acknowledged on recap (ISO). Non-empty means
|
|
1087
|
+
* the agent has seen it; the recap won't re-prompt every turn. The handoff
|
|
1088
|
+
* content is KEPT until a task in the phase starts (auto-clear) or the phase
|
|
1089
|
+
* completes — so a restart between read and resume does not lose context. */
|
|
1090
|
+
handoffReadAt: z.ZodDefault<z.ZodString>;
|
|
1091
|
+
/** Metadata for recently-cleared handoffs (newest-first, capped at 5). The
|
|
1092
|
+
* full content lives as .md files in .planner/handoff-archive/ (gitignored);
|
|
1093
|
+
* this array only holds the pointer + clear reason + timestamp, so the phase
|
|
1094
|
+
* JSON stays lean and the archive is recoverable. */
|
|
1095
|
+
handoffHistory: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
1096
|
+
/** Relative path under .planner/handoff-archive/ (e.g. <phaseId>-<ISO>.md). */
|
|
1097
|
+
file: z.ZodDefault<z.ZodString>;
|
|
1098
|
+
clearedAt: z.ZodString;
|
|
1099
|
+
/** Why the handoff was cleared: "task-started" | "phase-done" | "manual" | "superseded" | "imported". */
|
|
1100
|
+
reason: z.ZodDefault<z.ZodString>;
|
|
1101
|
+
}, "strip", z.ZodTypeAny, {
|
|
1102
|
+
file: string;
|
|
1103
|
+
clearedAt: string;
|
|
1104
|
+
reason: string;
|
|
1105
|
+
}, {
|
|
1106
|
+
clearedAt: string;
|
|
1107
|
+
file?: string | undefined;
|
|
1108
|
+
reason?: string | undefined;
|
|
1109
|
+
}>, "many">>;
|
|
1052
1110
|
}, "strip", z.ZodTypeAny, {
|
|
1053
1111
|
number: number;
|
|
1054
1112
|
dependencies: string[];
|
|
@@ -1130,6 +1188,12 @@ export declare const PhaseSchema: z.ZodObject<{
|
|
|
1130
1188
|
}[];
|
|
1131
1189
|
handoff: string;
|
|
1132
1190
|
handoffUpdatedAt: string;
|
|
1191
|
+
handoffReadAt: string;
|
|
1192
|
+
handoffHistory: {
|
|
1193
|
+
file: string;
|
|
1194
|
+
clearedAt: string;
|
|
1195
|
+
reason: string;
|
|
1196
|
+
}[];
|
|
1133
1197
|
featureId?: string | undefined;
|
|
1134
1198
|
}, {
|
|
1135
1199
|
number: number;
|
|
@@ -1213,9 +1277,16 @@ export declare const PhaseSchema: z.ZodObject<{
|
|
|
1213
1277
|
}[] | undefined;
|
|
1214
1278
|
handoff?: string | undefined;
|
|
1215
1279
|
handoffUpdatedAt?: string | undefined;
|
|
1280
|
+
handoffReadAt?: string | undefined;
|
|
1281
|
+
handoffHistory?: {
|
|
1282
|
+
clearedAt: string;
|
|
1283
|
+
file?: string | undefined;
|
|
1284
|
+
reason?: string | undefined;
|
|
1285
|
+
}[] | undefined;
|
|
1216
1286
|
}>;
|
|
1217
1287
|
export declare const FeatureSchema: z.ZodObject<{
|
|
1218
1288
|
id: z.ZodString;
|
|
1289
|
+
/** Global project-wide feature sequence (assigned once at creation from project.nextFeatureNumber; stable, gaps on delete). */
|
|
1219
1290
|
number: z.ZodDefault<z.ZodNumber>;
|
|
1220
1291
|
shortId: z.ZodDefault<z.ZodString>;
|
|
1221
1292
|
priority: z.ZodDefault<z.ZodNumber>;
|
|
@@ -1310,6 +1381,7 @@ export declare const FeatureSchema: z.ZodObject<{
|
|
|
1310
1381
|
export declare const FeaturesDocumentSchema: z.ZodObject<{
|
|
1311
1382
|
features: z.ZodArray<z.ZodObject<{
|
|
1312
1383
|
id: z.ZodString;
|
|
1384
|
+
/** Global project-wide feature sequence (assigned once at creation from project.nextFeatureNumber; stable, gaps on delete). */
|
|
1313
1385
|
number: z.ZodDefault<z.ZodNumber>;
|
|
1314
1386
|
shortId: z.ZodDefault<z.ZodString>;
|
|
1315
1387
|
priority: z.ZodDefault<z.ZodNumber>;
|
|
@@ -1712,6 +1784,10 @@ export declare const PlanWorkspaceSchema: z.ZodObject<{
|
|
|
1712
1784
|
rationale?: string | undefined;
|
|
1713
1785
|
implementationNotes?: string | undefined;
|
|
1714
1786
|
}>, "many">>;
|
|
1787
|
+
/** Monotonic global sequence counters — assigned at creation, never reused (gaps on delete). */
|
|
1788
|
+
nextFeatureNumber: z.ZodDefault<z.ZodNumber>;
|
|
1789
|
+
nextPhaseNumber: z.ZodDefault<z.ZodNumber>;
|
|
1790
|
+
nextTaskNumber: z.ZodDefault<z.ZodNumber>;
|
|
1715
1791
|
}, "strip", z.ZodTypeAny, {
|
|
1716
1792
|
name: string;
|
|
1717
1793
|
goal: string;
|
|
@@ -1738,6 +1814,9 @@ export declare const PlanWorkspaceSchema: z.ZodObject<{
|
|
|
1738
1814
|
implementationNotes: string;
|
|
1739
1815
|
acceptedAt: string;
|
|
1740
1816
|
}[];
|
|
1817
|
+
nextFeatureNumber: number;
|
|
1818
|
+
nextPhaseNumber: number;
|
|
1819
|
+
nextTaskNumber: number;
|
|
1741
1820
|
}, {
|
|
1742
1821
|
name: string;
|
|
1743
1822
|
workflowRules: {
|
|
@@ -1764,10 +1843,14 @@ export declare const PlanWorkspaceSchema: z.ZodObject<{
|
|
|
1764
1843
|
rationale?: string | undefined;
|
|
1765
1844
|
implementationNotes?: string | undefined;
|
|
1766
1845
|
}[] | undefined;
|
|
1846
|
+
nextFeatureNumber?: number | undefined;
|
|
1847
|
+
nextPhaseNumber?: number | undefined;
|
|
1848
|
+
nextTaskNumber?: number | undefined;
|
|
1767
1849
|
}>;
|
|
1768
1850
|
features: z.ZodObject<{
|
|
1769
1851
|
features: z.ZodArray<z.ZodObject<{
|
|
1770
1852
|
id: z.ZodString;
|
|
1853
|
+
/** Global project-wide feature sequence (assigned once at creation from project.nextFeatureNumber; stable, gaps on delete). */
|
|
1771
1854
|
number: z.ZodDefault<z.ZodNumber>;
|
|
1772
1855
|
shortId: z.ZodDefault<z.ZodString>;
|
|
1773
1856
|
priority: z.ZodDefault<z.ZodNumber>;
|
|
@@ -2020,6 +2103,7 @@ export declare const PlanWorkspaceSchema: z.ZodObject<{
|
|
|
2020
2103
|
phases: z.ZodArray<z.ZodObject<{
|
|
2021
2104
|
id: z.ZodString;
|
|
2022
2105
|
featureId: z.ZodOptional<z.ZodString>;
|
|
2106
|
+
/** Global project-wide phase sequence (assigned once at creation from project.nextPhaseNumber; stable, gaps on delete). Bare P00x is unambiguous. */
|
|
2023
2107
|
number: z.ZodNumber;
|
|
2024
2108
|
shortId: z.ZodDefault<z.ZodString>;
|
|
2025
2109
|
priority: z.ZodDefault<z.ZodNumber>;
|
|
@@ -2065,6 +2149,7 @@ export declare const PlanWorkspaceSchema: z.ZodObject<{
|
|
|
2065
2149
|
tasks: z.ZodDefault<z.ZodArray<z.ZodEffects<z.ZodObject<{
|
|
2066
2150
|
id: z.ZodString;
|
|
2067
2151
|
phaseId: z.ZodString;
|
|
2152
|
+
/** Global project-wide task sequence (assigned once at creation from project.nextTaskNumber; stable, gaps on delete). Bare T00x is unambiguous. */
|
|
2068
2153
|
number: z.ZodDefault<z.ZodNumber>;
|
|
2069
2154
|
shortId: z.ZodDefault<z.ZodString>;
|
|
2070
2155
|
priority: z.ZodDefault<z.ZodNumber>;
|
|
@@ -2347,6 +2432,30 @@ export declare const PlanWorkspaceSchema: z.ZodObject<{
|
|
|
2347
2432
|
updatedAt: z.ZodString;
|
|
2348
2433
|
handoff: z.ZodDefault<z.ZodString>;
|
|
2349
2434
|
handoffUpdatedAt: z.ZodDefault<z.ZodString>;
|
|
2435
|
+
/** When the handoff was last read/acknowledged on recap (ISO). Non-empty means
|
|
2436
|
+
* the agent has seen it; the recap won't re-prompt every turn. The handoff
|
|
2437
|
+
* content is KEPT until a task in the phase starts (auto-clear) or the phase
|
|
2438
|
+
* completes — so a restart between read and resume does not lose context. */
|
|
2439
|
+
handoffReadAt: z.ZodDefault<z.ZodString>;
|
|
2440
|
+
/** Metadata for recently-cleared handoffs (newest-first, capped at 5). The
|
|
2441
|
+
* full content lives as .md files in .planner/handoff-archive/ (gitignored);
|
|
2442
|
+
* this array only holds the pointer + clear reason + timestamp, so the phase
|
|
2443
|
+
* JSON stays lean and the archive is recoverable. */
|
|
2444
|
+
handoffHistory: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
2445
|
+
/** Relative path under .planner/handoff-archive/ (e.g. <phaseId>-<ISO>.md). */
|
|
2446
|
+
file: z.ZodDefault<z.ZodString>;
|
|
2447
|
+
clearedAt: z.ZodString;
|
|
2448
|
+
/** Why the handoff was cleared: "task-started" | "phase-done" | "manual" | "superseded" | "imported". */
|
|
2449
|
+
reason: z.ZodDefault<z.ZodString>;
|
|
2450
|
+
}, "strip", z.ZodTypeAny, {
|
|
2451
|
+
file: string;
|
|
2452
|
+
clearedAt: string;
|
|
2453
|
+
reason: string;
|
|
2454
|
+
}, {
|
|
2455
|
+
clearedAt: string;
|
|
2456
|
+
file?: string | undefined;
|
|
2457
|
+
reason?: string | undefined;
|
|
2458
|
+
}>, "many">>;
|
|
2350
2459
|
}, "strip", z.ZodTypeAny, {
|
|
2351
2460
|
number: number;
|
|
2352
2461
|
dependencies: string[];
|
|
@@ -2428,6 +2537,12 @@ export declare const PlanWorkspaceSchema: z.ZodObject<{
|
|
|
2428
2537
|
}[];
|
|
2429
2538
|
handoff: string;
|
|
2430
2539
|
handoffUpdatedAt: string;
|
|
2540
|
+
handoffReadAt: string;
|
|
2541
|
+
handoffHistory: {
|
|
2542
|
+
file: string;
|
|
2543
|
+
clearedAt: string;
|
|
2544
|
+
reason: string;
|
|
2545
|
+
}[];
|
|
2431
2546
|
featureId?: string | undefined;
|
|
2432
2547
|
}, {
|
|
2433
2548
|
number: number;
|
|
@@ -2511,6 +2626,12 @@ export declare const PlanWorkspaceSchema: z.ZodObject<{
|
|
|
2511
2626
|
}[] | undefined;
|
|
2512
2627
|
handoff?: string | undefined;
|
|
2513
2628
|
handoffUpdatedAt?: string | undefined;
|
|
2629
|
+
handoffReadAt?: string | undefined;
|
|
2630
|
+
handoffHistory?: {
|
|
2631
|
+
clearedAt: string;
|
|
2632
|
+
file?: string | undefined;
|
|
2633
|
+
reason?: string | undefined;
|
|
2634
|
+
}[] | undefined;
|
|
2514
2635
|
}>, "many">;
|
|
2515
2636
|
}, "strip", z.ZodTypeAny, {
|
|
2516
2637
|
features: {
|
|
@@ -2594,6 +2715,9 @@ export declare const PlanWorkspaceSchema: z.ZodObject<{
|
|
|
2594
2715
|
implementationNotes: string;
|
|
2595
2716
|
acceptedAt: string;
|
|
2596
2717
|
}[];
|
|
2718
|
+
nextFeatureNumber: number;
|
|
2719
|
+
nextPhaseNumber: number;
|
|
2720
|
+
nextTaskNumber: number;
|
|
2597
2721
|
};
|
|
2598
2722
|
phases: {
|
|
2599
2723
|
number: number;
|
|
@@ -2676,6 +2800,12 @@ export declare const PlanWorkspaceSchema: z.ZodObject<{
|
|
|
2676
2800
|
}[];
|
|
2677
2801
|
handoff: string;
|
|
2678
2802
|
handoffUpdatedAt: string;
|
|
2803
|
+
handoffReadAt: string;
|
|
2804
|
+
handoffHistory: {
|
|
2805
|
+
file: string;
|
|
2806
|
+
clearedAt: string;
|
|
2807
|
+
reason: string;
|
|
2808
|
+
}[];
|
|
2679
2809
|
featureId?: string | undefined;
|
|
2680
2810
|
}[];
|
|
2681
2811
|
}, {
|
|
@@ -2760,6 +2890,9 @@ export declare const PlanWorkspaceSchema: z.ZodObject<{
|
|
|
2760
2890
|
rationale?: string | undefined;
|
|
2761
2891
|
implementationNotes?: string | undefined;
|
|
2762
2892
|
}[] | undefined;
|
|
2893
|
+
nextFeatureNumber?: number | undefined;
|
|
2894
|
+
nextPhaseNumber?: number | undefined;
|
|
2895
|
+
nextTaskNumber?: number | undefined;
|
|
2763
2896
|
};
|
|
2764
2897
|
phases: {
|
|
2765
2898
|
number: number;
|
|
@@ -2843,6 +2976,12 @@ export declare const PlanWorkspaceSchema: z.ZodObject<{
|
|
|
2843
2976
|
}[] | undefined;
|
|
2844
2977
|
handoff?: string | undefined;
|
|
2845
2978
|
handoffUpdatedAt?: string | undefined;
|
|
2979
|
+
handoffReadAt?: string | undefined;
|
|
2980
|
+
handoffHistory?: {
|
|
2981
|
+
clearedAt: string;
|
|
2982
|
+
file?: string | undefined;
|
|
2983
|
+
reason?: string | undefined;
|
|
2984
|
+
}[] | undefined;
|
|
2846
2985
|
}[];
|
|
2847
2986
|
}>;
|
|
2848
2987
|
export type Timestamp = z.infer<typeof TimestampSchema>;
|
package/dist/schema.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,eAAe,aAAwB,CAAC;AACrD,eAAO,MAAM,UAAU,aAAiD,CAAC;AAEzE,eAAO,MAAM,kBAAkB;;;;;;;;;EAG7B,CAAC;AAEH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;EAK7B,CAAC;AAEH,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAmBhC,CAAC;AAEH,eAAO,MAAM,iBAAiB
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"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"}
|
package/dist/schema.js
CHANGED
|
@@ -37,6 +37,10 @@ export const ResumeFocusSchema = z.object({
|
|
|
37
37
|
currentPhaseId: z.string().default(""),
|
|
38
38
|
inProgressTaskIds: z.array(z.string().min(1)).default([]),
|
|
39
39
|
nextSteps: z.array(z.string().min(1)).default([]),
|
|
40
|
+
/** When `nextSteps` last changed (free-text can go stale; the recap surfaces
|
|
41
|
+
* this so staleness is visible). Preserved across refreshResume (which keeps
|
|
42
|
+
* existing nextSteps); bumped only when saveResume receives new nextSteps. */
|
|
43
|
+
nextStepsUpdatedAt: z.string().default(""),
|
|
40
44
|
blockers: z.array(z.string().min(1)).default([]),
|
|
41
45
|
notes: z.string().default(""),
|
|
42
46
|
lastSessionSummary: z.string().default(""),
|
|
@@ -87,6 +91,10 @@ export const ProjectSchema = z.object({
|
|
|
87
91
|
chatLanguage: z.string().default(""),
|
|
88
92
|
workflowRules: WorkflowRulesSchema,
|
|
89
93
|
acceptedDecisions: z.array(AcceptedDecisionSchema).default([]),
|
|
94
|
+
/** Monotonic global sequence counters — assigned at creation, never reused (gaps on delete). */
|
|
95
|
+
nextFeatureNumber: z.number().int().positive().default(1),
|
|
96
|
+
nextPhaseNumber: z.number().int().positive().default(1),
|
|
97
|
+
nextTaskNumber: z.number().int().positive().default(1),
|
|
90
98
|
});
|
|
91
99
|
export const SubtaskStatusSchema = z.enum(["planned", "in-progress", "done", "blocked", "canceled", "rejected", "deferred", "waiting"]);
|
|
92
100
|
export const TaskStatusSchema = z.enum(["planned", "in-progress", "done", "blocked", "canceled", "rejected", "deferred", "waiting"]);
|
|
@@ -137,6 +145,7 @@ export const StatusLogEntrySchema = z.object({
|
|
|
137
145
|
export const TaskSchema = z.object({
|
|
138
146
|
id: z.string(),
|
|
139
147
|
phaseId: z.string(),
|
|
148
|
+
/** Global project-wide task sequence (assigned once at creation from project.nextTaskNumber; stable, gaps on delete). Bare T00x is unambiguous. */
|
|
140
149
|
number: z.number().int().nonnegative().default(0),
|
|
141
150
|
shortId: z.string().regex(/^(|[A-Z2-9]{5})$/).default(""),
|
|
142
151
|
priority: z.number().int().nonnegative().default(0),
|
|
@@ -163,9 +172,17 @@ export const TaskSchema = z.object({
|
|
|
163
172
|
: { ...item, id: item.id || createChecklistItemId(task.id, index + 1, item.title), title: item.title.trim(), checked: item.checked ?? false })
|
|
164
173
|
.filter((item) => item.title.length > 0),
|
|
165
174
|
}));
|
|
175
|
+
export const HandoffHistoryEntrySchema = z.object({
|
|
176
|
+
/** Relative path under .planner/handoff-archive/ (e.g. <phaseId>-<ISO>.md). */
|
|
177
|
+
file: z.string().default(""),
|
|
178
|
+
clearedAt: TimestampSchema,
|
|
179
|
+
/** Why the handoff was cleared: "task-started" | "phase-done" | "manual" | "superseded" | "imported". */
|
|
180
|
+
reason: z.string().default(""),
|
|
181
|
+
});
|
|
166
182
|
export const PhaseSchema = z.object({
|
|
167
183
|
id: z.string(),
|
|
168
184
|
featureId: z.string().optional(),
|
|
185
|
+
/** Global project-wide phase sequence (assigned once at creation from project.nextPhaseNumber; stable, gaps on delete). Bare P00x is unambiguous. */
|
|
169
186
|
number: z.number().int().positive(),
|
|
170
187
|
shortId: z.string().regex(/^(|[A-Z2-9]{5})$/).default(""),
|
|
171
188
|
priority: z.number().int().nonnegative().default(0),
|
|
@@ -195,9 +212,20 @@ export const PhaseSchema = z.object({
|
|
|
195
212
|
updatedAt: TimestampSchema,
|
|
196
213
|
handoff: z.string().default(""),
|
|
197
214
|
handoffUpdatedAt: z.string().default(""),
|
|
215
|
+
/** When the handoff was last read/acknowledged on recap (ISO). Non-empty means
|
|
216
|
+
* the agent has seen it; the recap won't re-prompt every turn. The handoff
|
|
217
|
+
* content is KEPT until a task in the phase starts (auto-clear) or the phase
|
|
218
|
+
* completes — so a restart between read and resume does not lose context. */
|
|
219
|
+
handoffReadAt: z.string().default(""),
|
|
220
|
+
/** Metadata for recently-cleared handoffs (newest-first, capped at 5). The
|
|
221
|
+
* full content lives as .md files in .planner/handoff-archive/ (gitignored);
|
|
222
|
+
* this array only holds the pointer + clear reason + timestamp, so the phase
|
|
223
|
+
* JSON stays lean and the archive is recoverable. */
|
|
224
|
+
handoffHistory: z.array(HandoffHistoryEntrySchema).default([]),
|
|
198
225
|
});
|
|
199
226
|
export const FeatureSchema = z.object({
|
|
200
227
|
id: z.string(),
|
|
228
|
+
/** Global project-wide feature sequence (assigned once at creation from project.nextFeatureNumber; stable, gaps on delete). */
|
|
201
229
|
number: z.number().int().nonnegative().default(0),
|
|
202
230
|
shortId: z.string().regex(/^(|[A-Z2-9]{5})$/).default(""),
|
|
203
231
|
priority: z.number().int().nonnegative().default(0),
|
package/package.json
CHANGED