@agent-plan/core 0.2.19-next.18 → 0.2.19-next.19

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 CHANGED
@@ -4,6 +4,7 @@ export * from "./schema.js";
4
4
  export * from "./checklist.js";
5
5
  export * from "./recap.js";
6
6
  export * from "./display-status.js";
7
+ export * from "./task-context.js";
7
8
  export { PlanStore, PlanStoreError, setWriteBusyHook, setWriteNotifyHook, migrateToUuids, migrateToGlobalSequence, withFeatureLock, type PhaseHandoffSummary, type OrphanPhaseSummary } from "./plan-store.js";
8
9
  export { PlanRenderer } from "./renderer.js";
9
10
  export { ExportService } from "./export-service.js";
@@ -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,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,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
@@ -4,6 +4,7 @@ export * from "./schema.js";
4
4
  export * from "./checklist.js";
5
5
  export * from "./recap.js";
6
6
  export * from "./display-status.js";
7
+ export * from "./task-context.js";
7
8
  export { PlanStore, PlanStoreError, setWriteBusyHook, setWriteNotifyHook, migrateToUuids, migrateToGlobalSequence, withFeatureLock } from "./plan-store.js";
8
9
  export { PlanRenderer } from "./renderer.js";
9
10
  export { ExportService } from "./export-service.js";
package/dist/naming.d.ts CHANGED
@@ -18,9 +18,12 @@ export declare function validateResolvedTarget<T extends {
18
18
  error: string;
19
19
  }>;
20
20
  /** Generate a globally-unique short id (5 chars, Crockford Base32, e.g. `UUXD1`-style
21
- * but without 0/1/I/O). Retries until the id is not in `existing` (project-scoped
22
- * collision guard). Throws only in the impossible saturation case (~50 retries). */
23
- export declare function createShortId(existing?: Set<string>): string;
21
+ * but without 0/1/I/O). If `seed` is provided, the id is derived deterministically
22
+ * from a stable hash of the seed so two worktrees starting from the same commit
23
+ * produce identical shortIds for the same entity. Retries until the id is not in
24
+ * `existing` (project-scoped collision guard). Throws only in the impossible
25
+ * saturation case (~50 retries). */
26
+ export declare function createShortId(existing?: Set<string>, seed?: string): string;
24
27
  export declare function normalizeSlug(input: string): string;
25
28
  /** Normalize, truncate to maxLen, and strip dangling dashes so the result
26
29
  * always satisfies SlugSchema (/^[a-z0-9]+(?:-[a-z0-9]+)*$/). Returns fallback
@@ -1 +1 @@
1
- {"version":3,"file":"naming.d.ts","sourceRoot":"","sources":["../src/naming.ts"],"names":[],"mappings":"AAKA;iFACiF;AACjF,eAAO,MAAM,kBAAkB,qCAAqC,CAAC;AAErE,eAAO,MAAM,eAAe,IAAI,CAAC;AACjC,eAAO,MAAM,gBAAgB,QAAkB,CAAC;AAEhD,4EAA4E;AAC5E,eAAO,MAAM,YAAY,QAAoE,CAAC;AAE9F,wBAAgB,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAEtD;AAED;;gEAEgE;AAChE,wBAAsB,sBAAsB,CAAC,CAAC,SAAS;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,EACnE,IAAI,EAAE,SAAS,GAAG,OAAO,EACzB,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,GACnC,OAAO,CAAC;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAStD;AAGD;;qFAEqF;AACrF,wBAAgB,aAAa,CAAC,QAAQ,GAAE,GAAG,CAAC,MAAM,CAAa,GAAG,MAAM,CAUvE;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAOnD;AAED;;;;8BAI8B;AAC9B,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,SAAK,EAAE,QAAQ,SAAa,GAAG,MAAM,CAGnF;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE5D;AAED;;iBAEiB;AACjB,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,CAGlF;AAED,4DAA4D;AAC5D,wBAAgB,gBAAgB,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CAE9D;AAED,oFAAoF;AACpF,wBAAgB,oBAAoB,CAClC,KAAK,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAA;CAAE,EAChD,QAAQ,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,EAAE,GACzC,MAAM,GAAG,SAAS,CAEpB;AAED,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED,mFAAmF;AACnF,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAExD;AAED,0FAA0F;AAC1F,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAGtF;AAED,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAED,wBAAgB,mBAAmB,IAAI,MAAM,CAE5C;AAED,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAED,wBAAgB,eAAe,IAAI,MAAM,CAExC;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAE3F;AAED,wBAAgB,sBAAsB,IAAI,MAAM,CAE/C"}
1
+ {"version":3,"file":"naming.d.ts","sourceRoot":"","sources":["../src/naming.ts"],"names":[],"mappings":"AAKA;iFACiF;AACjF,eAAO,MAAM,kBAAkB,qCAAqC,CAAC;AAErE,eAAO,MAAM,eAAe,IAAI,CAAC;AACjC,eAAO,MAAM,gBAAgB,QAAkB,CAAC;AAEhD,4EAA4E;AAC5E,eAAO,MAAM,YAAY,QAAoE,CAAC;AAE9F,wBAAgB,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAEtD;AAED;;gEAEgE;AAChE,wBAAsB,sBAAsB,CAAC,CAAC,SAAS;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,EACnE,IAAI,EAAE,SAAS,GAAG,OAAO,EACzB,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,GACnC,OAAO,CAAC;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAStD;AAGD;;;;;qCAKqC;AACrC,wBAAgB,aAAa,CAAC,QAAQ,GAAE,GAAG,CAAC,MAAM,CAAa,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CA2BtF;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAOnD;AAED;;;;8BAI8B;AAC9B,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,SAAK,EAAE,QAAQ,SAAa,GAAG,MAAM,CAGnF;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE5D;AAED;;iBAEiB;AACjB,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,CAGlF;AAED,4DAA4D;AAC5D,wBAAgB,gBAAgB,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CAE9D;AAED,oFAAoF;AACpF,wBAAgB,oBAAoB,CAClC,KAAK,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAA;CAAE,EAChD,QAAQ,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,EAAE,GACzC,MAAM,GAAG,SAAS,CAEpB;AAED,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED,mFAAmF;AACnF,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAExD;AAED,0FAA0F;AAC1F,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAGtF;AAED,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAED,wBAAgB,mBAAmB,IAAI,MAAM,CAE5C;AAED,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAED,wBAAgB,eAAe,IAAI,MAAM,CAExC;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAE3F;AAED,wBAAgB,sBAAsB,IAAI,MAAM,CAE/C"}
package/dist/naming.js CHANGED
@@ -25,9 +25,30 @@ export async function validateResolvedTarget(kind, resolvedId, loader) {
25
25
  return { ok: true };
26
26
  }
27
27
  /** Generate a globally-unique short id (5 chars, Crockford Base32, e.g. `UUXD1`-style
28
- * but without 0/1/I/O). Retries until the id is not in `existing` (project-scoped
29
- * collision guard). Throws only in the impossible saturation case (~50 retries). */
30
- export function createShortId(existing = new Set()) {
28
+ * but without 0/1/I/O). If `seed` is provided, the id is derived deterministically
29
+ * from a stable hash of the seed so two worktrees starting from the same commit
30
+ * produce identical shortIds for the same entity. Retries until the id is not in
31
+ * `existing` (project-scoped collision guard). Throws only in the impossible
32
+ * saturation case (~50 retries). */
33
+ export function createShortId(existing = new Set(), seed) {
34
+ if (seed) {
35
+ // Stable string hash -> Crockford encoding.
36
+ let hash = 0;
37
+ for (const c of seed) {
38
+ hash = ((hash << 5) - hash + c.charCodeAt(0)) | 0;
39
+ }
40
+ const base = Math.abs(hash);
41
+ for (let offset = 0; offset < 64; offset += 1) {
42
+ let id = "";
43
+ let value = base + offset;
44
+ for (let i = 0; i < SHORT_ID_LENGTH; i += 1) {
45
+ id = CROCKFORD_ALPHABET[value % CROCKFORD_ALPHABET.length] + id;
46
+ value = Math.floor(value / CROCKFORD_ALPHABET.length);
47
+ }
48
+ if (!existing.has(id))
49
+ return id;
50
+ }
51
+ }
31
52
  const max = CROCKFORD_ALPHABET.length;
32
53
  for (let attempt = 0; attempt < 64; attempt += 1) {
33
54
  let id = "";
@@ -132,6 +132,17 @@ export declare class PlanStore {
132
132
  private codebasePath;
133
133
  private resumePath;
134
134
  private activityPath;
135
+ private localRoot;
136
+ private timestampPath;
137
+ private backupsDir;
138
+ private tmpDir;
139
+ private handoffArchiveDir;
140
+ /** One-time migration for plans created before .planner/.local/ existed.
141
+ * Moves a legacy root-level file into .local/ if the legacy file exists and
142
+ * the .local/ counterpart does not. Safe to call on every load. */
143
+ private migrateLegacyLocalFile;
144
+ private migrateLegacyGeneratedDir;
145
+ private migrateLegacyHandoffArchive;
135
146
  init(projectName: string): Promise<void>;
136
147
  exists(): Promise<boolean>;
137
148
  loadManifest(): Promise<Manifest>;
@@ -286,10 +297,6 @@ export declare class PlanStore {
286
297
  /** Set the handoff text for a phase + stamp handoffUpdatedAt. Atomic per-file
287
298
  * update via updatePhase (so the web UI refreshes via maybeAutoSync). */
288
299
  setPhaseHandoff(phaseId: string, text: string): Promise<void>;
289
- /** Directory where cleared handoff content is archived as .md files
290
- * (gitignored). Keeps the phase JSON lean while making past handoffs
291
- * recoverable + human-readable. */
292
- private handoffArchiveDir;
293
300
  /** Mark the phase handoff as read/acknowledged on recap (sets handoffReadAt).
294
301
  * Does NOT clear the handoff — content is kept until a task starts or the
295
302
  * phase completes, so a restart between read and resume does not lose it. */
@@ -323,9 +330,10 @@ export declare class PlanStore {
323
330
  deletePhase(phaseId: string): Promise<void>;
324
331
  /** Load the full workspace (manifest + phases + project + requirements + features) */
325
332
  loadWorkspace(): Promise<PlanWorkspace>;
326
- /** Load all data, render markdown, and write into generated/. */
333
+ /** Load all data, render markdown, and write into generated/. Skips files
334
+ * whose content is unchanged to avoid unnecessary backup churn. */
327
335
  writeGenerated(): Promise<string[]>;
328
- /** Update manifest.updatedAt to reflect a change. */
329
- private touchManifest;
336
+ /** Update .local/timestamp.json to reflect a change. */
337
+ private touchTimestamp;
330
338
  }
331
339
  //# sourceMappingURL=plan-store.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"plan-store.d.ts","sourceRoot":"","sources":["../src/plan-store.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"plan-store.d.ts","sourceRoot":"","sources":["../src/plan-store.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import { access, copyFile, mkdir, readdir, readFile, rename, rm, stat, unlink, writeFile } from "node:fs/promises";
2
- import { join } from "node:path";
3
- import { ZodError } from "zod";
4
- import { CodebaseProfileSchema, FeatureSchema, FeaturesDocumentSchema, ManifestSchema, PhaseSchema, ProjectSchema, RequirementsDocumentSchema, ResumeFocusSchema, ActivityLogSchema, } from "./schema.js";
2
+ import { basename, dirname, join } from "node:path";
3
+ import { z, ZodError } from "zod";
4
+ import { CodebaseProfileSchema, FeatureSchema, FeaturesDocumentSchema, ManifestSchema, PhaseSchema, ProjectSchema, RequirementsDocumentSchema, ResumeFocusSchema, ActivityLogSchema, TimestampSchema, } from "./schema.js";
5
5
  import { createFeatureId, createPhaseId, createRequirementId, createShortId, createStatusLogEntryId, createTaskId, formatPhaseRef, isLegacyPhaseId } from "./naming.js";
6
6
  import { deriveParentDisplay, fromCanonicalStatus } from "./display-status.js";
7
7
  function nowISO() {
@@ -118,14 +118,27 @@ export function withFeatureLock(featureId, fn) {
118
118
  featureLocks.delete(featureId);
119
119
  });
120
120
  }
121
- async function atomicWriteText(path, raw) {
121
+ async function atomicWriteText(path, raw, root) {
122
122
  return withWriteLock(path, async () => {
123
123
  writeBusyHook?.(true);
124
- const tmp = `${path}.tmp.${process.pid}.${Date.now()}`;
124
+ const localRoot = root ? join(root, ".local") : undefined;
125
+ const tmpDir = localRoot ? join(localRoot, "tmp") : dirname(path);
126
+ const backupsRoot = localRoot ? join(localRoot, "backups") : dirname(path);
127
+ const rel = localRoot && path.startsWith(localRoot)
128
+ ? path.slice(localRoot.length).replace(/^\//, "")
129
+ : root && path.startsWith(root)
130
+ ? path.slice(root.length).replace(/^\//, "")
131
+ : basename(path);
132
+ const backupRel = rel ? rel + ".bak" : basename(path) + ".bak";
133
+ const backupPath = join(backupsRoot, backupRel);
134
+ const tmpName = rel ? rel.replace(/[/\\]/g, "--") + `.tmp.${process.pid}.${Date.now()}` : `${basename(path)}.tmp.${process.pid}.${Date.now()}`;
135
+ const tmp = join(tmpDir, tmpName);
125
136
  try {
137
+ await mkdir(tmpDir, { recursive: true });
126
138
  await writeFile(tmp, raw, "utf-8");
127
139
  try {
128
- await copyFile(path, `${path}.bak`);
140
+ await mkdir(dirname(backupPath), { recursive: true });
141
+ await copyFile(path, backupPath);
129
142
  }
130
143
  catch { }
131
144
  await rename(tmp, path);
@@ -140,10 +153,10 @@ async function atomicWriteText(path, raw) {
140
153
  }
141
154
  });
142
155
  }
143
- async function atomicWriteJson(path, data) {
144
- return atomicWriteText(path, JSON.stringify(data, null, 2));
156
+ async function atomicWriteJson(path, data, root) {
157
+ return atomicWriteText(path, JSON.stringify(data, null, 2), root);
145
158
  }
146
- async function atomicUpdateJson(path, schema, updater) {
159
+ async function atomicUpdateJson(path, schema, updater, root) {
147
160
  // NOTE: write the file INLINE here, do NOT call atomicWriteJson/atomicWriteText,
148
161
  // because those re-acquire withWriteLock(path) — and we already hold it (below).
149
162
  // Re-entrant locking is not supported, so calling them would deadlock.
@@ -152,11 +165,23 @@ async function atomicUpdateJson(path, schema, updater) {
152
165
  const updated = updater(current);
153
166
  const parsed = schema.parse(updated);
154
167
  writeBusyHook?.(true);
155
- const tmp = `${path}.tmp.${process.pid}.${Date.now()}`;
168
+ const localRoot = root ? join(root, ".local") : undefined;
169
+ const tmpDir = localRoot ? join(localRoot, "tmp") : dirname(path);
170
+ const backupsRoot = localRoot ? join(localRoot, "backups") : dirname(path);
171
+ const rel = localRoot && path.startsWith(localRoot)
172
+ ? path.slice(localRoot.length).replace(/^\//, "")
173
+ : root && path.startsWith(root)
174
+ ? path.slice(root.length).replace(/^\//, "")
175
+ : basename(path);
176
+ const backupPath = join(backupsRoot, rel + ".bak");
177
+ const tmpName = rel ? rel.replace(/[/\\]/g, "--") + `.tmp.${process.pid}.${Date.now()}` : `${basename(path)}.tmp.${process.pid}.${Date.now()}`;
178
+ const tmp = join(tmpDir, tmpName);
156
179
  try {
180
+ await mkdir(tmpDir, { recursive: true });
157
181
  await writeFile(tmp, JSON.stringify(parsed, null, 2), "utf-8");
158
182
  try {
159
- await copyFile(path, `${path}.bak`);
183
+ await mkdir(dirname(backupPath), { recursive: true });
184
+ await copyFile(path, backupPath);
160
185
  }
161
186
  catch { }
162
187
  await rename(tmp, path);
@@ -608,7 +633,7 @@ export class PlanStore {
608
633
  }
609
634
  await mkdir(this.featuresDir(), { recursive: true });
610
635
  for (const feat of legacy.features) {
611
- await atomicWriteJson(this.featurePath(feat.id), feat);
636
+ await atomicWriteJson(this.featurePath(feat.id), feat, this.root);
612
637
  }
613
638
  await unlink(this.featuresPath()).catch(() => { });
614
639
  }
@@ -619,16 +644,81 @@ export class PlanStore {
619
644
  return join(this.phasesDir(), `${phaseId}.json`);
620
645
  }
621
646
  generatedDir() {
622
- return join(this.root, "generated");
647
+ return join(this.localRoot(), "generated");
623
648
  }
624
649
  codebasePath() {
625
650
  return join(this.root, "codebase.json");
626
651
  }
627
652
  resumePath() {
628
- return join(this.root, "resume.json");
653
+ return join(this.localRoot(), "resume.json");
629
654
  }
630
655
  activityPath() {
631
- return join(this.root, "activity.json");
656
+ return join(this.localRoot(), "activity.json");
657
+ }
658
+ localRoot() {
659
+ return join(this.root, ".local");
660
+ }
661
+ timestampPath() {
662
+ return join(this.localRoot(), "timestamp.json");
663
+ }
664
+ backupsDir() {
665
+ return join(this.localRoot(), "backups");
666
+ }
667
+ tmpDir() {
668
+ return join(this.localRoot(), "tmp");
669
+ }
670
+ handoffArchiveDir() {
671
+ return join(this.localRoot(), "handoff-archive");
672
+ }
673
+ /** One-time migration for plans created before .planner/.local/ existed.
674
+ * Moves a legacy root-level file into .local/ if the legacy file exists and
675
+ * the .local/ counterpart does not. Safe to call on every load. */
676
+ async migrateLegacyLocalFile(oldPath, newPath) {
677
+ try {
678
+ await access(oldPath);
679
+ }
680
+ catch {
681
+ return;
682
+ }
683
+ try {
684
+ await access(newPath);
685
+ return;
686
+ }
687
+ catch { }
688
+ await mkdir(dirname(newPath), { recursive: true });
689
+ await rename(oldPath, newPath);
690
+ }
691
+ async migrateLegacyGeneratedDir() {
692
+ const oldDir = join(this.root, "generated");
693
+ const newDir = this.generatedDir();
694
+ try {
695
+ await access(oldDir);
696
+ }
697
+ catch {
698
+ return;
699
+ }
700
+ try {
701
+ await access(newDir);
702
+ return;
703
+ }
704
+ catch { }
705
+ await rename(oldDir, newDir);
706
+ }
707
+ async migrateLegacyHandoffArchive() {
708
+ const oldDir = join(this.root, "handoff-archive");
709
+ const newDir = this.handoffArchiveDir();
710
+ try {
711
+ await access(oldDir);
712
+ }
713
+ catch {
714
+ return;
715
+ }
716
+ try {
717
+ await access(newDir);
718
+ return;
719
+ }
720
+ catch { }
721
+ await rename(oldDir, newDir);
632
722
  }
633
723
  // ── Init ─────────────────────────────────────────────────────────────
634
724
  async init(projectName) {
@@ -638,7 +728,11 @@ export class PlanStore {
638
728
  await mkdir(this.root, { recursive: true });
639
729
  await mkdir(this.phasesDir(), { recursive: true });
640
730
  await mkdir(this.featuresDir(), { recursive: true });
731
+ await mkdir(this.localRoot(), { recursive: true });
732
+ await mkdir(this.backupsDir(), { recursive: true });
733
+ await mkdir(this.tmpDir(), { recursive: true });
641
734
  await mkdir(join(this.generatedDir(), "phases"), { recursive: true });
735
+ await mkdir(this.handoffArchiveDir(), { recursive: true });
642
736
  await mkdir(join(this.root, "schema"), { recursive: true });
643
737
  await mkdir(join(this.root, "adapters"), { recursive: true });
644
738
  const manifest = {
@@ -648,7 +742,8 @@ export class PlanStore {
648
742
  createdAt: nowISO(),
649
743
  updatedAt: nowISO(),
650
744
  };
651
- await atomicWriteJson(this.manifestPath(), manifest);
745
+ await atomicWriteJson(this.manifestPath(), manifest, this.root);
746
+ await atomicWriteJson(this.timestampPath(), { updatedAt: manifest.updatedAt }, this.root);
652
747
  await this.saveProject({
653
748
  name: projectName,
654
749
  goal: "",
@@ -698,7 +793,7 @@ export class PlanStore {
698
793
  "- `project.json` — scope, rules, stack, tools",
699
794
  "- `requirements.json` — requirements and macro-tasks",
700
795
  "- `phases/` — one JSON file per phase",
701
- "- `generated/` — auto-generated markdown views",
796
+ "- `generated/` — auto-generated markdown views (under `.local/`)",
702
797
  "- `schema/plan.schema.json` — JSON Schema for tooling",
703
798
  ].join("\n");
704
799
  await writeFile(join(this.root, "README.md"), readme, "utf-8");
@@ -709,13 +804,8 @@ export class PlanStore {
709
804
  // timestamp (guardBypassUntil must NOT leak into git/other clones)
710
805
  // - generated/: auto-regenerated markdown views (derived from JSON; churn)
711
806
  await writeFile(join(this.root, ".gitignore"), [
712
- "# Agent Plan transient/derived files — do not track",
713
- "*.bak",
714
- "*.tmp.*",
715
- "resume.json",
716
- "resume.*.json",
717
- "generated/",
718
- "handoff-archive/",
807
+ "# Agent Plan transient/derived/session-local files — do not track",
808
+ ".local/",
719
809
  "",
720
810
  ].join("\n"), "utf-8");
721
811
  }
@@ -730,7 +820,23 @@ export class PlanStore {
730
820
  }
731
821
  // ── Loaders ──────────────────────────────────────────────────────────
732
822
  async loadManifest() {
733
- return readJson(this.manifestPath(), ManifestSchema);
823
+ const manifest = await readJson(this.manifestPath(), ManifestSchema);
824
+ try {
825
+ const timestamp = await readJson(this.timestampPath(), z.object({ updatedAt: TimestampSchema }));
826
+ manifest.updatedAt = timestamp.updatedAt;
827
+ }
828
+ catch {
829
+ // Legacy plan without .local/timestamp.json: bootstrap from manifest.updatedAt
830
+ // and create the timestamp file so subsequent writes stay in .local/.
831
+ try {
832
+ await mkdir(this.localRoot(), { recursive: true });
833
+ await atomicWriteJson(this.timestampPath(), { updatedAt: manifest.updatedAt }, this.root);
834
+ }
835
+ catch {
836
+ // ignore bootstrap failure
837
+ }
838
+ }
839
+ return manifest;
734
840
  }
735
841
  async loadProject() {
736
842
  return readJson(this.projectPath(), ProjectSchema);
@@ -847,10 +953,11 @@ export class PlanStore {
847
953
  }
848
954
  async saveCodebaseProfile(profile) {
849
955
  const parsed = CodebaseProfileSchema.parse(profile);
850
- await atomicWriteJson(this.codebasePath(), parsed);
851
- await this.touchManifest();
956
+ await atomicWriteJson(this.codebasePath(), parsed, this.root);
957
+ await this.touchTimestamp();
852
958
  }
853
959
  async loadResume() {
960
+ await this.migrateLegacyLocalFile(join(this.root, "resume.json"), this.resumePath());
854
961
  try {
855
962
  return await readJson(this.resumePath(), ResumeFocusSchema);
856
963
  }
@@ -871,8 +978,8 @@ export class PlanStore {
871
978
  : (resume.nextStepsUpdatedAt || existing?.nextStepsUpdatedAt || nowISO()),
872
979
  };
873
980
  const parsed = ResumeFocusSchema.parse(withTs);
874
- await atomicWriteJson(this.resumePath(), parsed);
875
- await this.touchManifest();
981
+ await atomicWriteJson(this.resumePath(), parsed, this.root);
982
+ await this.touchTimestamp();
876
983
  }
877
984
  /**
878
985
  * Authorize a temporary guard bypass so edit/write tools may proceed even
@@ -918,6 +1025,7 @@ export class PlanStore {
918
1025
  return until > Date.now();
919
1026
  }
920
1027
  async loadActivityLog() {
1028
+ await this.migrateLegacyLocalFile(join(this.root, "activity.json"), this.activityPath());
921
1029
  try {
922
1030
  return await readJson(this.activityPath(), ActivityLogSchema);
923
1031
  }
@@ -933,8 +1041,8 @@ export class PlanStore {
933
1041
  // Cap to last 200 entries
934
1042
  if (log.entries.length > 200)
935
1043
  log.entries = log.entries.slice(-200);
936
- await atomicWriteJson(this.activityPath(), { entries: log.entries });
937
- await this.touchManifest();
1044
+ await atomicWriteJson(this.activityPath(), { entries: log.entries }, this.root);
1045
+ await this.touchTimestamp();
938
1046
  return entry;
939
1047
  }
940
1048
  /** Derive an up-to-date resume focus from the current workspace state. */
@@ -1228,7 +1336,7 @@ export class PlanStore {
1228
1336
  const sortedFeatures = [...featuresDoc.features].sort((a, b) => a.number - b.number || a.createdAt.localeCompare(b.createdAt));
1229
1337
  sortedFeatures.forEach((f, index) => {
1230
1338
  if (!f.shortId) {
1231
- f.shortId = createShortId(existing);
1339
+ f.shortId = createShortId(existing, `feature:${f.number}:${f.id}`);
1232
1340
  existing.add(f.shortId);
1233
1341
  shortIdsAssigned += 1;
1234
1342
  featuresDirty = true;
@@ -1247,7 +1355,7 @@ export class PlanStore {
1247
1355
  for (const phase of phases) {
1248
1356
  let phaseDirty = false;
1249
1357
  if (!phase.shortId) {
1250
- phase.shortId = createShortId(existing);
1358
+ phase.shortId = createShortId(existing, `phase:${phase.number}:${phase.id}`);
1251
1359
  existing.add(phase.shortId);
1252
1360
  shortIdsAssigned += 1;
1253
1361
  phaseDirty = true;
@@ -1261,7 +1369,7 @@ export class PlanStore {
1261
1369
  const sortedTasks = [...phase.tasks].sort((a, b) => a.number - b.number || a.createdAt.localeCompare(b.createdAt));
1262
1370
  sortedTasks.forEach((t, index) => {
1263
1371
  if (!t.shortId) {
1264
- t.shortId = createShortId(existing);
1372
+ t.shortId = createShortId(existing, `task:${t.number}:${t.id}`);
1265
1373
  existing.add(t.shortId);
1266
1374
  shortIdsAssigned += 1;
1267
1375
  phaseDirty = true;
@@ -1509,7 +1617,7 @@ export class PlanStore {
1509
1617
  }
1510
1618
  // ── Savers ───────────────────────────────────────────────────────────
1511
1619
  async updateProject(updater) {
1512
- const updated = await atomicUpdateJson(this.projectPath(), ProjectSchema, updater);
1620
+ const updated = await atomicUpdateJson(this.projectPath(), ProjectSchema, updater, this.root);
1513
1621
  await this.maybeAutoSync();
1514
1622
  return updated;
1515
1623
  }
@@ -1525,14 +1633,14 @@ export class PlanStore {
1525
1633
  return updated;
1526
1634
  }
1527
1635
  async updateRequirements(updater) {
1528
- const updated = await atomicUpdateJson(this.requirementsPath(), RequirementsDocumentSchema, updater);
1636
+ const updated = await atomicUpdateJson(this.requirementsPath(), RequirementsDocumentSchema, updater, this.root);
1529
1637
  await this.maybeAutoSync();
1530
1638
  return updated;
1531
1639
  }
1532
1640
  async saveProject(project) {
1533
1641
  const parsed = ProjectSchema.parse(project);
1534
- await atomicWriteJson(this.projectPath(), parsed);
1535
- await this.touchManifest();
1642
+ await atomicWriteJson(this.projectPath(), parsed, this.root);
1643
+ await this.touchTimestamp();
1536
1644
  await this.maybeAutoSync();
1537
1645
  }
1538
1646
  async saveFeatures(features) {
@@ -1540,7 +1648,7 @@ export class PlanStore {
1540
1648
  await this.migrateLegacy();
1541
1649
  await this.saveFeaturesRaw(features);
1542
1650
  });
1543
- await this.touchManifest();
1651
+ await this.touchTimestamp();
1544
1652
  await this.maybeAutoSync();
1545
1653
  }
1546
1654
  /** Per-file write of all features + orphan reconcile. No lock (caller holds withFeaturesLock). */
@@ -1549,7 +1657,7 @@ export class PlanStore {
1549
1657
  await mkdir(this.featuresDir(), { recursive: true });
1550
1658
  const wantIds = new Set(parsed.features.map((f) => f.id));
1551
1659
  for (const feat of parsed.features) {
1552
- await atomicWriteJson(this.featurePath(feat.id), feat);
1660
+ await atomicWriteJson(this.featurePath(feat.id), feat, this.root);
1553
1661
  }
1554
1662
  // Orphan reconcile: remove feature files no longer in the document.
1555
1663
  try {
@@ -1573,21 +1681,26 @@ export class PlanStore {
1573
1681
  await this.migrateLegacy();
1574
1682
  await mkdir(this.featuresDir(), { recursive: true });
1575
1683
  const parsed = FeatureSchema.parse(feature);
1576
- await atomicWriteJson(this.featurePath(parsed.id), parsed);
1684
+ await atomicWriteJson(this.featurePath(parsed.id), parsed, this.root);
1577
1685
  });
1578
- await this.touchManifest();
1686
+ await this.touchTimestamp();
1579
1687
  await this.maybeAutoSync();
1580
1688
  }
1581
1689
  async saveRequirements(reqs) {
1582
1690
  const parsed = RequirementsDocumentSchema.parse(reqs);
1583
- await atomicWriteJson(this.requirementsPath(), parsed);
1584
- await this.touchManifest();
1691
+ await atomicWriteJson(this.requirementsPath(), parsed, this.root);
1692
+ await this.touchTimestamp();
1585
1693
  }
1586
1694
  async savePhase(phase) {
1587
1695
  const features = await this.loadRawFeatures();
1588
1696
  const resolvedFeatureId = resolveStoredFeatureId(features, phase.featureId);
1589
1697
  // Referential integrity: if a featureId is present but cannot be resolved
1590
- // to a known feature, REJECT — never persist an orphan phase.
1698
+ // to a known feature, REJECT — never persist an orphan featureId.
1699
+ // NOTE: a missing/empty featureId is intentionally ALLOWED here so that
1700
+ // legacy migrations, repair, and feature-delete (unlink) can persist phases
1701
+ // without a feature yet. The hard "featureId required" gate lives at the
1702
+ // adapter boundary (Pi phase_create/task_create and MCP planner-phase-add/
1703
+ // planner-task-add), which is where user-facing creation happens.
1591
1704
  if (phase.featureId && phase.featureId.trim() && !resolvedFeatureId) {
1592
1705
  throw new PlanStoreError(`Cannot save phase "${phase.title}": featureId "${phase.featureId}" does not match any existing feature. Use a valid feature UUID, F00x ref, or shortId.`);
1593
1706
  }
@@ -1596,8 +1709,8 @@ export class PlanStore {
1596
1709
  : phase;
1597
1710
  const parsed = PhaseSchema.parse(this.normalizePhaseDocument(normalizedInput).phase);
1598
1711
  await mkdir(this.phasesDir(), { recursive: true });
1599
- await atomicWriteJson(this.phasePath(parsed.id), parsed);
1600
- await this.touchManifest();
1712
+ await atomicWriteJson(this.phasePath(parsed.id), parsed, this.root);
1713
+ await this.touchTimestamp();
1601
1714
  await this.maybeAutoSync();
1602
1715
  }
1603
1716
  /** Atomic read-modify-write on a single phase file. Serializes concurrent
@@ -1636,12 +1749,6 @@ export class PlanStore {
1636
1749
  const now = new Date().toISOString();
1637
1750
  await this.updatePhase(phaseId, (phase) => ({ ...phase, handoff: text, handoffUpdatedAt: now }));
1638
1751
  }
1639
- /** Directory where cleared handoff content is archived as .md files
1640
- * (gitignored). Keeps the phase JSON lean while making past handoffs
1641
- * recoverable + human-readable. */
1642
- handoffArchiveDir() {
1643
- return join(this.root, "handoff-archive");
1644
- }
1645
1752
  /** Mark the phase handoff as read/acknowledged on recap (sets handoffReadAt).
1646
1753
  * Does NOT clear the handoff — content is kept until a task starts or the
1647
1754
  * phase completes, so a restart between read and resume does not lose it. */
@@ -1687,6 +1794,7 @@ export class PlanStore {
1687
1794
  * left unchanged as an audit trail. If the handoff is empty, this is a no-op.
1688
1795
  * reason: "task-started" | "phase-done" | "manual" | "superseded" | "imported". */
1689
1796
  async clearPhaseHandoff(phaseId, reason = "manual") {
1797
+ await this.migrateLegacyHandoffArchive();
1690
1798
  const phase = await this.loadPhase(phaseId).catch(() => null);
1691
1799
  if (!phase || phase.handoff === "")
1692
1800
  return; // nothing to archive
@@ -1696,14 +1804,17 @@ export class PlanStore {
1696
1804
  await mkdir(archiveDir, { recursive: true }).catch(() => { });
1697
1805
  const fileName = `${phaseId}-${safeTs}.md`;
1698
1806
  const filePath = join(archiveDir, fileName);
1699
- await atomicWriteText(filePath, phase.handoff);
1807
+ await atomicWriteText(filePath, phase.handoff, this.root);
1700
1808
  const entry = { file: `handoff-archive/${fileName}`, clearedAt, reason };
1701
1809
  // Cap history at 5: prepend new entry, drop oldest (and delete its file).
1702
1810
  const trimmed = [entry, ...(phase.handoffHistory ?? [])].slice(0, 5);
1703
1811
  const dropped = (phase.handoffHistory ?? []).slice(4); // entries beyond index 4 after prepend
1704
1812
  for (const d of dropped) {
1705
- if (d?.file)
1706
- await unlink(join(this.root, d.file)).catch(() => { });
1813
+ if (!d?.file)
1814
+ continue;
1815
+ // Legacy entries used `.planner/handoff-archive/...`; new entries use `.planner/.local/handoff-archive/...`.
1816
+ await unlink(join(this.handoffArchiveDir(), basename(d.file))).catch(() => { });
1817
+ await unlink(join(this.root, d.file)).catch(() => { });
1707
1818
  }
1708
1819
  await this.updatePhase(phaseId, (p) => ({ ...p, handoff: "", handoffHistory: trimmed }));
1709
1820
  }
@@ -1775,7 +1886,7 @@ export class PlanStore {
1775
1886
  }
1776
1887
  return doc;
1777
1888
  });
1778
- await this.touchManifest();
1889
+ await this.touchTimestamp();
1779
1890
  await this.writeGenerated();
1780
1891
  return { found, removed: found };
1781
1892
  });
@@ -1787,7 +1898,7 @@ export class PlanStore {
1787
1898
  catch {
1788
1899
  // already gone
1789
1900
  }
1790
- await this.touchManifest();
1901
+ await this.touchTimestamp();
1791
1902
  }
1792
1903
  // ── Workspace-level operations ─────────────────────────────────────
1793
1904
  /** Load the full workspace (manifest + phases + project + requirements + features) */
@@ -1800,8 +1911,10 @@ export class PlanStore {
1800
1911
  return { manifest, phases, project, features, requirements };
1801
1912
  }
1802
1913
  // ── Markdown generation ────────────────────────────────────────────
1803
- /** Load all data, render markdown, and write into generated/. */
1914
+ /** Load all data, render markdown, and write into generated/. Skips files
1915
+ * whose content is unchanged to avoid unnecessary backup churn. */
1804
1916
  async writeGenerated() {
1917
+ await this.migrateLegacyGeneratedDir();
1805
1918
  const { PlanRenderer } = await import("./renderer.js");
1806
1919
  const plan = await this.loadAll();
1807
1920
  const renderer = new PlanRenderer();
@@ -1817,21 +1930,27 @@ export class PlanStore {
1817
1930
  if (dir !== genDir) {
1818
1931
  await mkdir(dir, { recursive: true });
1819
1932
  }
1933
+ try {
1934
+ const existing = await readFile(fullPath, "utf-8");
1935
+ if (existing === content)
1936
+ continue;
1937
+ }
1938
+ catch {
1939
+ // file does not exist yet — write it
1940
+ }
1820
1941
  await writeFile(fullPath, content, "utf-8");
1821
1942
  written.push(relPath);
1822
1943
  }
1823
1944
  return written;
1824
1945
  }
1825
1946
  // ── Touch ────────────────────────────────────────────────────────────
1826
- /** Update manifest.updatedAt to reflect a change. */
1827
- async touchManifest() {
1947
+ /** Update .local/timestamp.json to reflect a change. */
1948
+ async touchTimestamp() {
1828
1949
  try {
1829
- const m = await this.loadManifest();
1830
- m.updatedAt = nowISO();
1831
- await atomicWriteJson(this.manifestPath(), m);
1950
+ await atomicWriteJson(this.timestampPath(), { updatedAt: nowISO() }, this.root);
1832
1951
  }
1833
1952
  catch {
1834
- // if manifest doesn't exist yet, skip
1953
+ // if .local/ doesn't exist yet, skip
1835
1954
  }
1836
1955
  }
1837
1956
  }
package/dist/schema.d.ts CHANGED
@@ -779,7 +779,7 @@ export declare const TaskSchema: z.ZodEffects<z.ZodObject<{
779
779
  completedAt?: string | undefined;
780
780
  }>;
781
781
  export declare const HandoffHistoryEntrySchema: z.ZodObject<{
782
- /** Relative path under .planner/handoff-archive/ (e.g. <phaseId>-<ISO>.md). */
782
+ /** Relative path under .planner/.local/handoff-archive/ (e.g. <phaseId>-<ISO>.md). */
783
783
  file: z.ZodDefault<z.ZodString>;
784
784
  clearedAt: z.ZodString;
785
785
  /** Why the handoff was cleared: "task-started" | "phase-done" | "manual" | "superseded" | "imported". */
@@ -1146,11 +1146,11 @@ export declare const PhaseSchema: z.ZodObject<{
1146
1146
  * completes — so a restart between read and resume does not lose context. */
1147
1147
  handoffReadAt: z.ZodDefault<z.ZodString>;
1148
1148
  /** Metadata for recently-cleared handoffs (newest-first, capped at 5). The
1149
- * full content lives as .md files in .planner/handoff-archive/ (gitignored);
1149
+ * full content lives as .md files in .planner/.local/handoff-archive/ (gitignored);
1150
1150
  * this array only holds the pointer + clear reason + timestamp, so the phase
1151
1151
  * JSON stays lean and the archive is recoverable. */
1152
1152
  handoffHistory: z.ZodDefault<z.ZodArray<z.ZodObject<{
1153
- /** Relative path under .planner/handoff-archive/ (e.g. <phaseId>-<ISO>.md). */
1153
+ /** Relative path under .planner/.local/handoff-archive/ (e.g. <phaseId>-<ISO>.md). */
1154
1154
  file: z.ZodDefault<z.ZodString>;
1155
1155
  clearedAt: z.ZodString;
1156
1156
  /** Why the handoff was cleared: "task-started" | "phase-done" | "manual" | "superseded" | "imported". */
@@ -2700,11 +2700,11 @@ export declare const PlanWorkspaceSchema: z.ZodObject<{
2700
2700
  * completes — so a restart between read and resume does not lose context. */
2701
2701
  handoffReadAt: z.ZodDefault<z.ZodString>;
2702
2702
  /** Metadata for recently-cleared handoffs (newest-first, capped at 5). The
2703
- * full content lives as .md files in .planner/handoff-archive/ (gitignored);
2703
+ * full content lives as .md files in .planner/.local/handoff-archive/ (gitignored);
2704
2704
  * this array only holds the pointer + clear reason + timestamp, so the phase
2705
2705
  * JSON stays lean and the archive is recoverable. */
2706
2706
  handoffHistory: z.ZodDefault<z.ZodArray<z.ZodObject<{
2707
- /** Relative path under .planner/handoff-archive/ (e.g. <phaseId>-<ISO>.md). */
2707
+ /** Relative path under .planner/.local/handoff-archive/ (e.g. <phaseId>-<ISO>.md). */
2708
2708
  file: z.ZodDefault<z.ZodString>;
2709
2709
  clearedAt: z.ZodString;
2710
2710
  /** Why the handoff was cleared: "task-started" | "phase-done" | "manual" | "superseded" | "imported". */
@@ -1 +1 @@
1
- {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"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"}
package/dist/schema.js CHANGED
@@ -189,7 +189,7 @@ export const TaskSchema = z.object({
189
189
  .filter((item) => item.title.length > 0),
190
190
  }));
191
191
  export const HandoffHistoryEntrySchema = z.object({
192
- /** Relative path under .planner/handoff-archive/ (e.g. <phaseId>-<ISO>.md). */
192
+ /** Relative path under .planner/.local/handoff-archive/ (e.g. <phaseId>-<ISO>.md). */
193
193
  file: z.string().default(""),
194
194
  clearedAt: TimestampSchema,
195
195
  /** Why the handoff was cleared: "task-started" | "phase-done" | "manual" | "superseded" | "imported". */
@@ -237,7 +237,7 @@ export const PhaseSchema = z.object({
237
237
  * completes — so a restart between read and resume does not lose context. */
238
238
  handoffReadAt: z.string().default(""),
239
239
  /** Metadata for recently-cleared handoffs (newest-first, capped at 5). The
240
- * full content lives as .md files in .planner/handoff-archive/ (gitignored);
240
+ * full content lives as .md files in .planner/.local/handoff-archive/ (gitignored);
241
241
  * this array only holds the pointer + clear reason + timestamp, so the phase
242
242
  * JSON stays lean and the archive is recoverable. */
243
243
  handoffHistory: z.array(HandoffHistoryEntrySchema).default([]),
@@ -0,0 +1,16 @@
1
+ import type { Feature, Phase } from "./schema.js";
2
+ /**
3
+ * Build a compact, agent-facing context block that surfaces the PARENT PHASE
4
+ * (and grandparent FEATURE) description when a task is started. The phase
5
+ * description carries the shared design context (file:line refs, architecture,
6
+ * current state, behaviors to preserve) that EVERY task in the phase inherits.
7
+ *
8
+ * Injecting this into the `task_start` tool response guarantees the agent sees
9
+ * the phase-level context in the exact moment it begins work — instead of
10
+ * relying on the agent to voluntarily read it beforehand.
11
+ *
12
+ * Harness-agnostic: returns a plain markdown string. Both the Pi adapter and
13
+ * the MCP server append this to their `task_start` confirmation text.
14
+ */
15
+ export declare function buildPhaseContextBlock(phase: Phase, feature: Feature | undefined): string;
16
+ //# sourceMappingURL=task-context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task-context.d.ts","sourceRoot":"","sources":["../src/task-context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAGlD;;;;;;;;;;;;GAYG;AACH,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE,OAAO,GAAG,SAAS,GAC3B,MAAM,CAiCR"}
@@ -0,0 +1,48 @@
1
+ import { formatPhaseRef } from "./naming.js";
2
+ /**
3
+ * Build a compact, agent-facing context block that surfaces the PARENT PHASE
4
+ * (and grandparent FEATURE) description when a task is started. The phase
5
+ * description carries the shared design context (file:line refs, architecture,
6
+ * current state, behaviors to preserve) that EVERY task in the phase inherits.
7
+ *
8
+ * Injecting this into the `task_start` tool response guarantees the agent sees
9
+ * the phase-level context in the exact moment it begins work — instead of
10
+ * relying on the agent to voluntarily read it beforehand.
11
+ *
12
+ * Harness-agnostic: returns a plain markdown string. Both the Pi adapter and
13
+ * the MCP server append this to their `task_start` confirmation text.
14
+ */
15
+ export function buildPhaseContextBlock(phase, feature) {
16
+ const lines = [];
17
+ const phaseRef = formatPhaseRef(phase.number, feature?.number);
18
+ lines.push(`\n📋 Phase context — read this BEFORE touching code:`);
19
+ lines.push(`Phase ${phaseRef} — ${phase.title}`);
20
+ if (phase.summary && phase.summary.trim()) {
21
+ lines.push(`Summary: ${phase.summary.trim()}`);
22
+ }
23
+ if (phase.description && phase.description.trim()) {
24
+ lines.push(`\nPhase description:\n${phase.description.trim()}`);
25
+ }
26
+ const bullet = (label, items) => {
27
+ if (items && items.length > 0) {
28
+ lines.push(`\n${label}:`);
29
+ for (const it of items)
30
+ lines.push(` - ${it}`);
31
+ }
32
+ };
33
+ bullet("Goals", phase.goals);
34
+ bullet("Non-goals", phase.nonGoals);
35
+ bullet("Dependencies", phase.dependencies);
36
+ bullet("Risks", phase.risks);
37
+ bullet("Open questions", phase.openQuestions);
38
+ bullet("Decisions", phase.decisions);
39
+ bullet("Completion criteria", phase.completionCriteria);
40
+ if (feature) {
41
+ lines.push(`\nFeature F${String(feature.number).padStart(3, "0")} — ${feature.name}`);
42
+ if (feature.description && feature.description.trim()) {
43
+ lines.push(`\nFeature description:\n${feature.description.trim()}`);
44
+ }
45
+ }
46
+ lines.push(`\n(End of phase context. Now proceed with the task.)`);
47
+ return lines.join("\n");
48
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-plan/core",
3
- "version": "0.2.19-next.18",
3
+ "version": "0.2.19-next.19",
4
4
  "private": false,
5
5
  "description": "Harness-agnostic core for Agent Plan: schemas, persistence, ordering, status rollups, and markdown rendering.",
6
6
  "license": "MIT",