@agent-plan/core 0.2.19-next.1 → 0.2.19-next.3
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/plan-store.d.ts +26 -12
- package/dist/plan-store.d.ts.map +1 -1
- package/dist/plan-store.js +87 -50
- package/dist/schema.d.ts +99 -0
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +17 -0
- package/package.json +1 -1
package/dist/plan-store.d.ts
CHANGED
|
@@ -63,7 +63,6 @@ export declare class PlanStore {
|
|
|
63
63
|
private codebasePath;
|
|
64
64
|
private resumePath;
|
|
65
65
|
private activityPath;
|
|
66
|
-
private handoffPath;
|
|
67
66
|
init(projectName: string): Promise<void>;
|
|
68
67
|
exists(): Promise<boolean>;
|
|
69
68
|
loadManifest(): Promise<Manifest>;
|
|
@@ -90,14 +89,6 @@ export declare class PlanStore {
|
|
|
90
89
|
/** True when a guard bypass is currently active (not expired). */
|
|
91
90
|
isGuardBypassed(): Promise<boolean>;
|
|
92
91
|
loadActivityLog(): Promise<ActivityLog>;
|
|
93
|
-
handoffExists(): Promise<boolean>;
|
|
94
|
-
loadHandoff(): Promise<{
|
|
95
|
-
content: string;
|
|
96
|
-
createdAt: string;
|
|
97
|
-
updatedAt: string;
|
|
98
|
-
} | null>;
|
|
99
|
-
saveHandoff(content: string): Promise<void>;
|
|
100
|
-
deleteHandoff(): Promise<void>;
|
|
101
92
|
appendActivity(type: string, ref: string, summary: string): Promise<ActivityEntry>;
|
|
102
93
|
/** Derive an up-to-date resume focus from the current workspace state. */
|
|
103
94
|
refreshResume(notes?: string, lastSessionSummary?: string): Promise<ResumeFocus>;
|
|
@@ -188,9 +179,32 @@ export declare class PlanStore {
|
|
|
188
179
|
/** Set the handoff text for a phase + stamp handoffUpdatedAt. Atomic per-file
|
|
189
180
|
* update via updatePhase (so the web UI refreshes via maybeAutoSync). */
|
|
190
181
|
setPhaseHandoff(phaseId: string, text: string): Promise<void>;
|
|
191
|
-
/**
|
|
192
|
-
*
|
|
193
|
-
|
|
182
|
+
/** Directory where cleared handoff content is archived as .md files
|
|
183
|
+
* (gitignored). Keeps the phase JSON lean while making past handoffs
|
|
184
|
+
* recoverable + human-readable. */
|
|
185
|
+
private handoffArchiveDir;
|
|
186
|
+
/** Mark the phase handoff as read/acknowledged on recap (sets handoffReadAt).
|
|
187
|
+
* Does NOT clear the handoff — content is kept until a task starts or the
|
|
188
|
+
* phase completes, so a restart between read and resume does not lose it. */
|
|
189
|
+
markHandoffRead(phaseId: string): Promise<void>;
|
|
190
|
+
/** One-time import of a legacy .planner/HANDOFF.md file (file-based handoff
|
|
191
|
+
* from before F004) into the entity-scoped phase.handoff. Idempotent: if the
|
|
192
|
+
* file is absent or empty, no-op. If it exists + non-empty + the target phase
|
|
193
|
+
* has no handoff, writes the content onto the current in-progress phase (or
|
|
194
|
+
* the first phase if none in-progress) with an "imported" handoffHistory entry,
|
|
195
|
+
* then renames the file to HANDOFF.md.bak so it won't re-import. If the target
|
|
196
|
+
* already has a handoff, the entity-scoped one wins and the file is just .bak'd. */
|
|
197
|
+
importLegacyHandoffFile(): Promise<{
|
|
198
|
+
imported: boolean;
|
|
199
|
+
phaseRef?: string;
|
|
200
|
+
}>;
|
|
201
|
+
/** Clear the handoff for a phase, archiving its content first. The handoff
|
|
202
|
+
* markdown is written to .planner/handoff-archive/<phaseId>-<ISO>.md and a
|
|
203
|
+
* metadata entry { file, clearedAt, reason } is prepended to handoffHistory
|
|
204
|
+
* (capped at 5; oldest file is deleted when trimmed). handoffUpdatedAt is
|
|
205
|
+
* left unchanged as an audit trail. If the handoff is empty, this is a no-op.
|
|
206
|
+
* reason: "task-started" | "phase-done" | "manual" | "superseded" | "imported". */
|
|
207
|
+
clearPhaseHandoff(phaseId: string, reason?: string): Promise<void>;
|
|
194
208
|
/** List all phases that have a non-empty handoff, newest first, with a
|
|
195
209
|
* human-readable composite ref (P00x or P00x(F00x)) and a first-line excerpt. */
|
|
196
210
|
listHandoffs(): Promise<PhaseHandoffSummary[]>;
|
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":"AAEA,OAAO,EAGL,KAAK,OAAO,EACZ,KAAK,gBAAgB,EAGrB,KAAK,QAAQ,EAEb,KAAK,KAAK,EAEV,KAAK,aAAa,EAElB,KAAK,OAAO,EAEZ,KAAK,oBAAoB,EAIzB,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,eAAe,EACpB,KAAK,WAAW,EACjB,MAAM,aAAa,CAAC;AAOrB,qBAAa,cAAe,SAAQ,KAAK;aAGrB,KAAK,CAAC,EAAE,OAAO;gBAD/B,OAAO,EAAE,MAAM,EACC,KAAK,CAAC,EAAE,OAAO,YAAA;CAKlC;AAeD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC,GAAG,SAAS,GAAG,IAAI,CAElF;AAKD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,GAAG,IAAI,CAEvE;AAaD,wBAAgB,eAAe,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAStF;AAmDD,mFAAmF;AACnF,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,iEAAiE;IACjE,YAAY,EAAE,MAAM,CAAC;IACrB,iEAAiE;IACjE,SAAS,EAAE,MAAM,CAAC;IAClB,yFAAyF;IACzF,SAAS,EAAE,MAAM,CAAC;CACnB;AASD,wBAAsB,cAAc,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAsEpE;AA4BD,qBAAa,SAAS;IACpB,SAAgB,IAAI,EAAE,MAAM,CAAC;IAC7B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,SAAS,CAAS;IAO1B,OAAO,CAAC,eAAe,CAAS;gBAEpB,IAAI,EAAE,MAAM;IAIxB;;4EAEwE;IACxE,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IAEpC;;;2BAGuB;YACT,UAAU;IAUxB,2EAA2E;IACrE,oBAAoB,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAI/D;;oFAEgF;IAC1E,QAAQ,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;YAIrC,aAAa;IAK3B,OAAO,CAAC,cAAc;IAUtB,OAAO,CAAC,yBAAyB;IAUjC,OAAO,CAAC,sBAAsB;IAc9B,OAAO,CAAC,0BAA0B;IAuE5B,uBAAuB,IAAI,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;
|
|
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
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { access, copyFile, mkdir, readdir, readFile, rename,
|
|
1
|
+
import { access, copyFile, mkdir, readdir, readFile, rename, unlink, writeFile } from "node:fs/promises";
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
import { CodebaseProfileSchema, FeatureSchema, FeaturesDocumentSchema, ManifestSchema, PhaseSchema, ProjectSchema, RequirementsDocumentSchema, ResumeFocusSchema, ActivityLogSchema, } from "./schema.js";
|
|
4
4
|
import { createFeatureId, createPhaseId, createRequirementId, createShortId, createTaskId, formatPhaseRef, isLegacyPhaseId } from "./naming.js";
|
|
@@ -338,7 +338,7 @@ export class PlanStore {
|
|
|
338
338
|
};
|
|
339
339
|
}
|
|
340
340
|
async ensureStructureOrdering() {
|
|
341
|
-
|
|
341
|
+
const result = await this.runAsBatch(async () => {
|
|
342
342
|
const featuresDoc = await this.loadFeatures();
|
|
343
343
|
const phases = await this.loadAllPhases();
|
|
344
344
|
const normalized = this.normalizeStructureSnapshot(featuresDoc, phases);
|
|
@@ -350,6 +350,10 @@ export class PlanStore {
|
|
|
350
350
|
}
|
|
351
351
|
return { changed: true };
|
|
352
352
|
});
|
|
353
|
+
// One-time import of a legacy file-based HANDOFF.md (pre-F004) into the
|
|
354
|
+
// entity-scoped phase.handoff. Idempotent — renames the file to .bak.
|
|
355
|
+
await this.importLegacyHandoffFile().catch(() => { });
|
|
356
|
+
return result;
|
|
353
357
|
}
|
|
354
358
|
// ── Path helpers ─────────────────────────────────────────────────────
|
|
355
359
|
manifestPath() {
|
|
@@ -411,9 +415,6 @@ export class PlanStore {
|
|
|
411
415
|
activityPath() {
|
|
412
416
|
return join(this.root, "activity.json");
|
|
413
417
|
}
|
|
414
|
-
handoffPath() {
|
|
415
|
-
return join(this.root, "HANDOFF.md");
|
|
416
|
-
}
|
|
417
418
|
// ── Init ─────────────────────────────────────────────────────────────
|
|
418
419
|
async init(projectName) {
|
|
419
420
|
if (await this.exists()) {
|
|
@@ -482,12 +483,20 @@ export class PlanStore {
|
|
|
482
483
|
"- `schema/plan.schema.json` — JSON Schema for tooling",
|
|
483
484
|
].join("\n");
|
|
484
485
|
await writeFile(join(this.root, "README.md"), readme, "utf-8");
|
|
485
|
-
// Write a .gitignore inside .planner/ so transient
|
|
486
|
+
// Write a .gitignore inside .planner/ so transient/derived files are
|
|
486
487
|
// not tracked by the host project's git. Git respects nested .gitignore.
|
|
488
|
+
// - *.bak/*.tmp.*: crash backups from atomic writes
|
|
489
|
+
// - resume.json: per-session resume focus + the machine-local guard-bypass
|
|
490
|
+
// timestamp (guardBypassUntil must NOT leak into git/other clones)
|
|
491
|
+
// - generated/: auto-regenerated markdown views (derived from JSON; churn)
|
|
487
492
|
await writeFile(join(this.root, ".gitignore"), [
|
|
488
|
-
"# Agent Plan transient files — do not track",
|
|
493
|
+
"# Agent Plan transient/derived files — do not track",
|
|
489
494
|
"*.bak",
|
|
490
495
|
"*.tmp.*",
|
|
496
|
+
"resume.json",
|
|
497
|
+
"resume.*.json",
|
|
498
|
+
"generated/",
|
|
499
|
+
"handoff-archive/",
|
|
491
500
|
"",
|
|
492
501
|
].join("\n"), "utf-8");
|
|
493
502
|
}
|
|
@@ -636,44 +645,6 @@ export class PlanStore {
|
|
|
636
645
|
return { entries: [] };
|
|
637
646
|
}
|
|
638
647
|
}
|
|
639
|
-
async handoffExists() {
|
|
640
|
-
try {
|
|
641
|
-
await access(this.handoffPath());
|
|
642
|
-
return true;
|
|
643
|
-
}
|
|
644
|
-
catch {
|
|
645
|
-
return false;
|
|
646
|
-
}
|
|
647
|
-
}
|
|
648
|
-
async loadHandoff() {
|
|
649
|
-
try {
|
|
650
|
-
const [content, info] = await Promise.all([
|
|
651
|
-
readFile(this.handoffPath(), "utf-8"),
|
|
652
|
-
stat(this.handoffPath()),
|
|
653
|
-
]);
|
|
654
|
-
const createdAt = content.match(/^Created at:\s*(.+)$/m)?.[1]?.trim() ?? info.birthtime.toISOString();
|
|
655
|
-
const updatedAt = content.match(/^Updated at:\s*(.+)$/m)?.[1]?.trim() ?? info.mtime.toISOString();
|
|
656
|
-
return {
|
|
657
|
-
content,
|
|
658
|
-
createdAt,
|
|
659
|
-
updatedAt,
|
|
660
|
-
};
|
|
661
|
-
}
|
|
662
|
-
catch {
|
|
663
|
-
return null;
|
|
664
|
-
}
|
|
665
|
-
}
|
|
666
|
-
async saveHandoff(content) {
|
|
667
|
-
await atomicWriteText(this.handoffPath(), content);
|
|
668
|
-
await this.touchManifest();
|
|
669
|
-
}
|
|
670
|
-
async deleteHandoff() {
|
|
671
|
-
try {
|
|
672
|
-
await unlink(this.handoffPath());
|
|
673
|
-
}
|
|
674
|
-
catch { }
|
|
675
|
-
await this.touchManifest();
|
|
676
|
-
}
|
|
677
648
|
async appendActivity(type, ref, summary) {
|
|
678
649
|
const log = await this.loadActivityLog();
|
|
679
650
|
const id = `act-${log.entries.length + 1}-${type}`;
|
|
@@ -1121,7 +1092,7 @@ export class PlanStore {
|
|
|
1121
1092
|
const phase = await this.loadPhase(phaseId);
|
|
1122
1093
|
let cleared = null;
|
|
1123
1094
|
if (phase.status === "done" && phase.handoff !== "") {
|
|
1124
|
-
await this.
|
|
1095
|
+
await this.clearPhaseHandoff(phaseId, "phase-done");
|
|
1125
1096
|
const features = await this.loadFeatures();
|
|
1126
1097
|
const feature = features.features.find((f) => f.id === phase.featureId);
|
|
1127
1098
|
cleared = formatPhaseRef(phase.number, feature?.number);
|
|
@@ -1239,10 +1210,76 @@ export class PlanStore {
|
|
|
1239
1210
|
const now = new Date().toISOString();
|
|
1240
1211
|
await this.updatePhase(phaseId, (phase) => ({ ...phase, handoff: text, handoffUpdatedAt: now }));
|
|
1241
1212
|
}
|
|
1242
|
-
/**
|
|
1243
|
-
*
|
|
1244
|
-
|
|
1245
|
-
|
|
1213
|
+
/** Directory where cleared handoff content is archived as .md files
|
|
1214
|
+
* (gitignored). Keeps the phase JSON lean while making past handoffs
|
|
1215
|
+
* recoverable + human-readable. */
|
|
1216
|
+
handoffArchiveDir() {
|
|
1217
|
+
return join(this.root, "handoff-archive");
|
|
1218
|
+
}
|
|
1219
|
+
/** Mark the phase handoff as read/acknowledged on recap (sets handoffReadAt).
|
|
1220
|
+
* Does NOT clear the handoff — content is kept until a task starts or the
|
|
1221
|
+
* phase completes, so a restart between read and resume does not lose it. */
|
|
1222
|
+
async markHandoffRead(phaseId) {
|
|
1223
|
+
await this.updatePhase(phaseId, (phase) => ({ ...phase, handoffReadAt: nowISO() }));
|
|
1224
|
+
}
|
|
1225
|
+
/** One-time import of a legacy .planner/HANDOFF.md file (file-based handoff
|
|
1226
|
+
* from before F004) into the entity-scoped phase.handoff. Idempotent: if the
|
|
1227
|
+
* file is absent or empty, no-op. If it exists + non-empty + the target phase
|
|
1228
|
+
* has no handoff, writes the content onto the current in-progress phase (or
|
|
1229
|
+
* the first phase if none in-progress) with an "imported" handoffHistory entry,
|
|
1230
|
+
* then renames the file to HANDOFF.md.bak so it won't re-import. If the target
|
|
1231
|
+
* already has a handoff, the entity-scoped one wins and the file is just .bak'd. */
|
|
1232
|
+
async importLegacyHandoffFile() {
|
|
1233
|
+
const filePath = join(this.root, "HANDOFF.md");
|
|
1234
|
+
const content = await readFile(filePath, "utf-8").catch(() => null);
|
|
1235
|
+
if (content === null)
|
|
1236
|
+
return { imported: false };
|
|
1237
|
+
if (content.trim() === "") {
|
|
1238
|
+
await rename(filePath, filePath + ".bak").catch(() => { });
|
|
1239
|
+
return { imported: false };
|
|
1240
|
+
}
|
|
1241
|
+
const phases = await this.loadAllPhases();
|
|
1242
|
+
const target = phases.find((p) => p.status === "in-progress") ?? phases[0] ?? null;
|
|
1243
|
+
if (!target)
|
|
1244
|
+
return { imported: false }; // no phases yet — leave file for a later run
|
|
1245
|
+
if ((target.handoff ?? "") === "") {
|
|
1246
|
+
await this.setPhaseHandoff(target.id, content + "\n\n<!-- imported from legacy .planner/HANDOFF.md -->\n");
|
|
1247
|
+
await this.updatePhase(target.id, (p) => ({
|
|
1248
|
+
...p,
|
|
1249
|
+
handoffHistory: [{ file: "(legacy HANDOFF.md)", clearedAt: nowISO(), reason: "imported" }, ...(p.handoffHistory ?? [])].slice(0, 5),
|
|
1250
|
+
}));
|
|
1251
|
+
}
|
|
1252
|
+
await rename(filePath, filePath + ".bak").catch(() => { });
|
|
1253
|
+
const features = await this.loadFeatures();
|
|
1254
|
+
const feat = features.features.find((f) => f.id === target.featureId);
|
|
1255
|
+
return { imported: true, phaseRef: formatPhaseRef(target.number, feat?.number) };
|
|
1256
|
+
}
|
|
1257
|
+
/** Clear the handoff for a phase, archiving its content first. The handoff
|
|
1258
|
+
* markdown is written to .planner/handoff-archive/<phaseId>-<ISO>.md and a
|
|
1259
|
+
* metadata entry { file, clearedAt, reason } is prepended to handoffHistory
|
|
1260
|
+
* (capped at 5; oldest file is deleted when trimmed). handoffUpdatedAt is
|
|
1261
|
+
* left unchanged as an audit trail. If the handoff is empty, this is a no-op.
|
|
1262
|
+
* reason: "task-started" | "phase-done" | "manual" | "superseded" | "imported". */
|
|
1263
|
+
async clearPhaseHandoff(phaseId, reason = "manual") {
|
|
1264
|
+
const phase = await this.loadPhase(phaseId).catch(() => null);
|
|
1265
|
+
if (!phase || phase.handoff === "")
|
|
1266
|
+
return; // nothing to archive
|
|
1267
|
+
const clearedAt = nowISO();
|
|
1268
|
+
const safeTs = clearedAt.replace(/[:.]/g, "-");
|
|
1269
|
+
const archiveDir = this.handoffArchiveDir();
|
|
1270
|
+
await mkdir(archiveDir, { recursive: true }).catch(() => { });
|
|
1271
|
+
const fileName = `${phaseId}-${safeTs}.md`;
|
|
1272
|
+
const filePath = join(archiveDir, fileName);
|
|
1273
|
+
await atomicWriteText(filePath, phase.handoff);
|
|
1274
|
+
const entry = { file: `handoff-archive/${fileName}`, clearedAt, reason };
|
|
1275
|
+
// Cap history at 5: prepend new entry, drop oldest (and delete its file).
|
|
1276
|
+
const trimmed = [entry, ...(phase.handoffHistory ?? [])].slice(0, 5);
|
|
1277
|
+
const dropped = (phase.handoffHistory ?? []).slice(4); // entries beyond index 4 after prepend
|
|
1278
|
+
for (const d of dropped) {
|
|
1279
|
+
if (d?.file)
|
|
1280
|
+
await unlink(join(this.root, d.file)).catch(() => { });
|
|
1281
|
+
}
|
|
1282
|
+
await this.updatePhase(phaseId, (p) => ({ ...p, handoff: "", handoffHistory: trimmed }));
|
|
1246
1283
|
}
|
|
1247
1284
|
/** List all phases that have a non-empty handoff, newest first, with a
|
|
1248
1285
|
* human-readable composite ref (P00x or P00x(F00x)) and a first-line excerpt. */
|
package/dist/schema.d.ts
CHANGED
|
@@ -719,6 +719,21 @@ export declare const TaskSchema: z.ZodEffects<z.ZodObject<{
|
|
|
719
719
|
startedAt?: string | undefined;
|
|
720
720
|
completedAt?: string | undefined;
|
|
721
721
|
}>;
|
|
722
|
+
export declare const HandoffHistoryEntrySchema: z.ZodObject<{
|
|
723
|
+
/** Relative path under .planner/handoff-archive/ (e.g. <phaseId>-<ISO>.md). */
|
|
724
|
+
file: z.ZodDefault<z.ZodString>;
|
|
725
|
+
clearedAt: z.ZodString;
|
|
726
|
+
/** Why the handoff was cleared: "task-started" | "phase-done" | "manual" | "superseded" | "imported". */
|
|
727
|
+
reason: z.ZodDefault<z.ZodString>;
|
|
728
|
+
}, "strip", z.ZodTypeAny, {
|
|
729
|
+
file: string;
|
|
730
|
+
clearedAt: string;
|
|
731
|
+
reason: string;
|
|
732
|
+
}, {
|
|
733
|
+
clearedAt: string;
|
|
734
|
+
file?: string | undefined;
|
|
735
|
+
reason?: string | undefined;
|
|
736
|
+
}>;
|
|
722
737
|
export declare const PhaseSchema: z.ZodObject<{
|
|
723
738
|
id: z.ZodString;
|
|
724
739
|
featureId: z.ZodOptional<z.ZodString>;
|
|
@@ -1049,6 +1064,30 @@ export declare const PhaseSchema: z.ZodObject<{
|
|
|
1049
1064
|
updatedAt: z.ZodString;
|
|
1050
1065
|
handoff: z.ZodDefault<z.ZodString>;
|
|
1051
1066
|
handoffUpdatedAt: z.ZodDefault<z.ZodString>;
|
|
1067
|
+
/** When the handoff was last read/acknowledged on recap (ISO). Non-empty means
|
|
1068
|
+
* the agent has seen it; the recap won't re-prompt every turn. The handoff
|
|
1069
|
+
* content is KEPT until a task in the phase starts (auto-clear) or the phase
|
|
1070
|
+
* completes — so a restart between read and resume does not lose context. */
|
|
1071
|
+
handoffReadAt: z.ZodDefault<z.ZodString>;
|
|
1072
|
+
/** Metadata for recently-cleared handoffs (newest-first, capped at 5). The
|
|
1073
|
+
* full content lives as .md files in .planner/handoff-archive/ (gitignored);
|
|
1074
|
+
* this array only holds the pointer + clear reason + timestamp, so the phase
|
|
1075
|
+
* JSON stays lean and the archive is recoverable. */
|
|
1076
|
+
handoffHistory: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
1077
|
+
/** Relative path under .planner/handoff-archive/ (e.g. <phaseId>-<ISO>.md). */
|
|
1078
|
+
file: z.ZodDefault<z.ZodString>;
|
|
1079
|
+
clearedAt: z.ZodString;
|
|
1080
|
+
/** Why the handoff was cleared: "task-started" | "phase-done" | "manual" | "superseded" | "imported". */
|
|
1081
|
+
reason: z.ZodDefault<z.ZodString>;
|
|
1082
|
+
}, "strip", z.ZodTypeAny, {
|
|
1083
|
+
file: string;
|
|
1084
|
+
clearedAt: string;
|
|
1085
|
+
reason: string;
|
|
1086
|
+
}, {
|
|
1087
|
+
clearedAt: string;
|
|
1088
|
+
file?: string | undefined;
|
|
1089
|
+
reason?: string | undefined;
|
|
1090
|
+
}>, "many">>;
|
|
1052
1091
|
}, "strip", z.ZodTypeAny, {
|
|
1053
1092
|
number: number;
|
|
1054
1093
|
dependencies: string[];
|
|
@@ -1130,6 +1169,12 @@ export declare const PhaseSchema: z.ZodObject<{
|
|
|
1130
1169
|
}[];
|
|
1131
1170
|
handoff: string;
|
|
1132
1171
|
handoffUpdatedAt: string;
|
|
1172
|
+
handoffReadAt: string;
|
|
1173
|
+
handoffHistory: {
|
|
1174
|
+
file: string;
|
|
1175
|
+
clearedAt: string;
|
|
1176
|
+
reason: string;
|
|
1177
|
+
}[];
|
|
1133
1178
|
featureId?: string | undefined;
|
|
1134
1179
|
}, {
|
|
1135
1180
|
number: number;
|
|
@@ -1213,6 +1258,12 @@ export declare const PhaseSchema: z.ZodObject<{
|
|
|
1213
1258
|
}[] | undefined;
|
|
1214
1259
|
handoff?: string | undefined;
|
|
1215
1260
|
handoffUpdatedAt?: string | undefined;
|
|
1261
|
+
handoffReadAt?: string | undefined;
|
|
1262
|
+
handoffHistory?: {
|
|
1263
|
+
clearedAt: string;
|
|
1264
|
+
file?: string | undefined;
|
|
1265
|
+
reason?: string | undefined;
|
|
1266
|
+
}[] | undefined;
|
|
1216
1267
|
}>;
|
|
1217
1268
|
export declare const FeatureSchema: z.ZodObject<{
|
|
1218
1269
|
id: z.ZodString;
|
|
@@ -2347,6 +2398,30 @@ export declare const PlanWorkspaceSchema: z.ZodObject<{
|
|
|
2347
2398
|
updatedAt: z.ZodString;
|
|
2348
2399
|
handoff: z.ZodDefault<z.ZodString>;
|
|
2349
2400
|
handoffUpdatedAt: z.ZodDefault<z.ZodString>;
|
|
2401
|
+
/** When the handoff was last read/acknowledged on recap (ISO). Non-empty means
|
|
2402
|
+
* the agent has seen it; the recap won't re-prompt every turn. The handoff
|
|
2403
|
+
* content is KEPT until a task in the phase starts (auto-clear) or the phase
|
|
2404
|
+
* completes — so a restart between read and resume does not lose context. */
|
|
2405
|
+
handoffReadAt: z.ZodDefault<z.ZodString>;
|
|
2406
|
+
/** Metadata for recently-cleared handoffs (newest-first, capped at 5). The
|
|
2407
|
+
* full content lives as .md files in .planner/handoff-archive/ (gitignored);
|
|
2408
|
+
* this array only holds the pointer + clear reason + timestamp, so the phase
|
|
2409
|
+
* JSON stays lean and the archive is recoverable. */
|
|
2410
|
+
handoffHistory: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
2411
|
+
/** Relative path under .planner/handoff-archive/ (e.g. <phaseId>-<ISO>.md). */
|
|
2412
|
+
file: z.ZodDefault<z.ZodString>;
|
|
2413
|
+
clearedAt: z.ZodString;
|
|
2414
|
+
/** Why the handoff was cleared: "task-started" | "phase-done" | "manual" | "superseded" | "imported". */
|
|
2415
|
+
reason: z.ZodDefault<z.ZodString>;
|
|
2416
|
+
}, "strip", z.ZodTypeAny, {
|
|
2417
|
+
file: string;
|
|
2418
|
+
clearedAt: string;
|
|
2419
|
+
reason: string;
|
|
2420
|
+
}, {
|
|
2421
|
+
clearedAt: string;
|
|
2422
|
+
file?: string | undefined;
|
|
2423
|
+
reason?: string | undefined;
|
|
2424
|
+
}>, "many">>;
|
|
2350
2425
|
}, "strip", z.ZodTypeAny, {
|
|
2351
2426
|
number: number;
|
|
2352
2427
|
dependencies: string[];
|
|
@@ -2428,6 +2503,12 @@ export declare const PlanWorkspaceSchema: z.ZodObject<{
|
|
|
2428
2503
|
}[];
|
|
2429
2504
|
handoff: string;
|
|
2430
2505
|
handoffUpdatedAt: string;
|
|
2506
|
+
handoffReadAt: string;
|
|
2507
|
+
handoffHistory: {
|
|
2508
|
+
file: string;
|
|
2509
|
+
clearedAt: string;
|
|
2510
|
+
reason: string;
|
|
2511
|
+
}[];
|
|
2431
2512
|
featureId?: string | undefined;
|
|
2432
2513
|
}, {
|
|
2433
2514
|
number: number;
|
|
@@ -2511,6 +2592,12 @@ export declare const PlanWorkspaceSchema: z.ZodObject<{
|
|
|
2511
2592
|
}[] | undefined;
|
|
2512
2593
|
handoff?: string | undefined;
|
|
2513
2594
|
handoffUpdatedAt?: string | undefined;
|
|
2595
|
+
handoffReadAt?: string | undefined;
|
|
2596
|
+
handoffHistory?: {
|
|
2597
|
+
clearedAt: string;
|
|
2598
|
+
file?: string | undefined;
|
|
2599
|
+
reason?: string | undefined;
|
|
2600
|
+
}[] | undefined;
|
|
2514
2601
|
}>, "many">;
|
|
2515
2602
|
}, "strip", z.ZodTypeAny, {
|
|
2516
2603
|
features: {
|
|
@@ -2676,6 +2763,12 @@ export declare const PlanWorkspaceSchema: z.ZodObject<{
|
|
|
2676
2763
|
}[];
|
|
2677
2764
|
handoff: string;
|
|
2678
2765
|
handoffUpdatedAt: string;
|
|
2766
|
+
handoffReadAt: string;
|
|
2767
|
+
handoffHistory: {
|
|
2768
|
+
file: string;
|
|
2769
|
+
clearedAt: string;
|
|
2770
|
+
reason: string;
|
|
2771
|
+
}[];
|
|
2679
2772
|
featureId?: string | undefined;
|
|
2680
2773
|
}[];
|
|
2681
2774
|
}, {
|
|
@@ -2843,6 +2936,12 @@ export declare const PlanWorkspaceSchema: z.ZodObject<{
|
|
|
2843
2936
|
}[] | undefined;
|
|
2844
2937
|
handoff?: string | undefined;
|
|
2845
2938
|
handoffUpdatedAt?: string | undefined;
|
|
2939
|
+
handoffReadAt?: string | undefined;
|
|
2940
|
+
handoffHistory?: {
|
|
2941
|
+
clearedAt: string;
|
|
2942
|
+
file?: string | undefined;
|
|
2943
|
+
reason?: string | undefined;
|
|
2944
|
+
}[] | undefined;
|
|
2846
2945
|
}[];
|
|
2847
2946
|
}>;
|
|
2848
2947
|
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;;;;;;;;;;;;;;;;;;;;;;;;;;;EAS5B,CAAC;AAEH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;EAM9B,CAAC;AAEH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAE5B,CAAC;AAEH,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;EAMzB,CAAC;AAEH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;EAI9B,CAAC;AAEH,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;EAOjC,CAAC;AAEH,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAexB,CAAC;AAEH,eAAO,MAAM,mBAAmB,yGAAuG,CAAC;AACxI,eAAO,MAAM,gBAAgB,yGAAuG,CAAC;AACrI,eAAO,MAAM,iBAAiB,+HAA6H,CAAC;AAC5J,eAAO,MAAM,uBAAuB,yGAAuG,CAAC;AAC5I,eAAO,MAAM,mBAAmB,yGAAuG,CAAC;AAExI,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;EAOxB,CAAC;AAEH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;EAI9B,CAAC;AAIH,wEAAwE;AACxE,eAAO,MAAM,8BAA8B,aAEzC,CAAC;AAEH;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAK7E;AAED,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;EAO/B,CAAC;AAEH,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA4BpB,CAAC;AAEJ,eAAO,MAAM,WAAW
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"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"}
|
package/dist/schema.js
CHANGED
|
@@ -163,6 +163,13 @@ export const TaskSchema = z.object({
|
|
|
163
163
|
: { ...item, id: item.id || createChecklistItemId(task.id, index + 1, item.title), title: item.title.trim(), checked: item.checked ?? false })
|
|
164
164
|
.filter((item) => item.title.length > 0),
|
|
165
165
|
}));
|
|
166
|
+
export const HandoffHistoryEntrySchema = z.object({
|
|
167
|
+
/** Relative path under .planner/handoff-archive/ (e.g. <phaseId>-<ISO>.md). */
|
|
168
|
+
file: z.string().default(""),
|
|
169
|
+
clearedAt: TimestampSchema,
|
|
170
|
+
/** Why the handoff was cleared: "task-started" | "phase-done" | "manual" | "superseded" | "imported". */
|
|
171
|
+
reason: z.string().default(""),
|
|
172
|
+
});
|
|
166
173
|
export const PhaseSchema = z.object({
|
|
167
174
|
id: z.string(),
|
|
168
175
|
featureId: z.string().optional(),
|
|
@@ -195,6 +202,16 @@ export const PhaseSchema = z.object({
|
|
|
195
202
|
updatedAt: TimestampSchema,
|
|
196
203
|
handoff: z.string().default(""),
|
|
197
204
|
handoffUpdatedAt: z.string().default(""),
|
|
205
|
+
/** When the handoff was last read/acknowledged on recap (ISO). Non-empty means
|
|
206
|
+
* the agent has seen it; the recap won't re-prompt every turn. The handoff
|
|
207
|
+
* content is KEPT until a task in the phase starts (auto-clear) or the phase
|
|
208
|
+
* completes — so a restart between read and resume does not lose context. */
|
|
209
|
+
handoffReadAt: z.string().default(""),
|
|
210
|
+
/** Metadata for recently-cleared handoffs (newest-first, capped at 5). The
|
|
211
|
+
* full content lives as .md files in .planner/handoff-archive/ (gitignored);
|
|
212
|
+
* this array only holds the pointer + clear reason + timestamp, so the phase
|
|
213
|
+
* JSON stays lean and the archive is recoverable. */
|
|
214
|
+
handoffHistory: z.array(HandoffHistoryEntrySchema).default([]),
|
|
198
215
|
});
|
|
199
216
|
export const FeatureSchema = z.object({
|
|
200
217
|
id: z.string(),
|
package/package.json
CHANGED