@agent-plan/core 0.2.19-next.0 → 0.2.19-next.2

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
@@ -1,6 +1,7 @@
1
1
  export * from "./naming.js";
2
2
  export * from "./refs.js";
3
3
  export * from "./schema.js";
4
+ export * from "./recap.js";
4
5
  export { PlanStore, PlanStoreError, setWriteBusyHook, setWriteNotifyHook, migrateToUuids, withFeatureLock, type PhaseHandoffSummary } from "./plan-store.js";
5
6
  export { PlanRenderer } from "./renderer.js";
6
7
  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,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,cAAc,EAAE,eAAe,EAAE,KAAK,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAC7J,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,YAAY,CAAC;AAC3B,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,cAAc,EAAE,eAAe,EAAE,KAAK,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAC7J,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
@@ -1,6 +1,7 @@
1
1
  export * from "./naming.js";
2
2
  export * from "./refs.js";
3
3
  export * from "./schema.js";
4
+ export * from "./recap.js";
4
5
  export { PlanStore, PlanStoreError, setWriteBusyHook, setWriteNotifyHook, migrateToUuids, withFeatureLock } from "./plan-store.js";
5
6
  export { PlanRenderer } from "./renderer.js";
6
7
  export { ExportService } from "./export-service.js";
package/dist/naming.d.ts CHANGED
@@ -20,6 +20,15 @@ export declare function formatThreeDigitNumber(value: number): string;
20
20
  * feature number is known. Harness-agnostic (used by core handoff listing +
21
21
  * adapters). */
22
22
  export declare function formatPhaseRef(phaseNumber: number, featureNumber?: number): string;
23
+ /** Human-readable feature ref: `F00x`. Harness-agnostic. */
24
+ export declare function formatFeatureRef(featureNumber: number): string;
25
+ /** Find the parent feature's number for a phase (for P00x(F00x) composite refs). */
26
+ export declare function featureNumberOfPhase(phase: {
27
+ featureId?: string | null | undefined;
28
+ }, features: {
29
+ id: string;
30
+ number: number;
31
+ }[]): number | undefined;
23
32
  export declare function createPhaseId(): string;
24
33
  /** True for legacy phase ids that are NOT feature-scoped (e.g. `phase-01-...`). */
25
34
  export declare function isLegacyPhaseId(phaseId: string): boolean;
@@ -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;;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,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"}
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;;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"}
package/dist/naming.js CHANGED
@@ -51,6 +51,14 @@ export function formatPhaseRef(phaseNumber, featureNumber) {
51
51
  const p = `P${formatThreeDigitNumber(phaseNumber)}`;
52
52
  return featureNumber != null ? `${p}(F${formatThreeDigitNumber(featureNumber)})` : p;
53
53
  }
54
+ /** Human-readable feature ref: `F00x`. Harness-agnostic. */
55
+ export function formatFeatureRef(featureNumber) {
56
+ return `F${formatThreeDigitNumber(featureNumber)}`;
57
+ }
58
+ /** Find the parent feature's number for a phase (for P00x(F00x) composite refs). */
59
+ export function featureNumberOfPhase(phase, features) {
60
+ return phase.featureId ? features.find((f) => f.id === phase.featureId)?.number : undefined;
61
+ }
54
62
  export function createPhaseId() {
55
63
  return randomUUID();
56
64
  }
@@ -34,6 +34,10 @@ export declare class PlanStore {
34
34
  private runAsBatch;
35
35
  /** Public batch wrapper used by the module-level migrateToUuids helper. */
36
36
  runBatchForMigration<T>(fn: () => Promise<T>): Promise<T>;
37
+ /** Public batch wrapper: suspend autoSync (status rollup) for a sequence of
38
+ * writes. Use for priority-only reorders so they don't recompute phase/feature
39
+ * status (a reorder must not flip a partially-done feature to in-progress). */
40
+ runBatch<T>(fn: () => Promise<T>): Promise<T>;
37
41
  private maybeAutoSync;
38
42
  private normalizeTasks;
39
43
  private normalizeFeaturesDocument;
@@ -65,6 +69,10 @@ export declare class PlanStore {
65
69
  loadManifest(): Promise<Manifest>;
66
70
  loadProject(): Promise<Project>;
67
71
  loadPhase(phaseId: string): Promise<Phase>;
72
+ /** Read raw feature files WITHOUT the derived `status` field. Used
73
+ * internally so loadFeatures/loadAll can derive status from phases without
74
+ * double-loading. */
75
+ private loadRawFeatures;
68
76
  loadFeatures(): Promise<FeaturesDocument>;
69
77
  loadCodebaseProfile(): Promise<CodebaseProfile | null>;
70
78
  saveCodebaseProfile(profile: CodebaseProfile): Promise<void>;
@@ -155,10 +163,10 @@ export declare class PlanStore {
155
163
  private derivePhaseStatus;
156
164
  private deriveFeatureStatus;
157
165
  syncStatuses(): Promise<string[]>;
158
- /** Optimized rollup: syncs only the affected phase and its parent feature.
159
- * Drastically reduces write operations and 'busy' window for task updates.
160
- * Returns the composite ref of the phase if its handoff was auto-cleared
161
- * (phase transitioned to done), else null. */
166
+ /** Auto-clear a phase's handoff when its DERIVED status is done. Status itself
167
+ * is no longer persisted (derived on read), so the only remaining side effect
168
+ * of a task→done transition is clearing a stale handoff on a completed phase.
169
+ * Returns the composite ref of the phase if its handoff was cleared, else null. */
162
170
  syncTaskStatusRollup(phaseId: string): Promise<string | null>;
163
171
  updateProject(updater: (p: Project) => Project): Promise<Project>;
164
172
  updateFeatures(updater: (f: FeaturesDocument) => FeaturesDocument): Promise<FeaturesDocument>;
@@ -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,6 +1,6 @@
1
1
  import { access, copyFile, mkdir, readdir, readFile, rename, stat, unlink, writeFile } from "node:fs/promises";
2
2
  import { join } from "node:path";
3
- import { CodebaseProfileSchema, FeatureSchema, FeaturesDocumentSchema, ManifestSchema, PhaseSchema, PlanWorkspaceSchema, ProjectSchema, RequirementsDocumentSchema, ResumeFocusSchema, ActivityLogSchema, } from "./schema.js";
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";
5
5
  function nowISO() {
6
6
  return new Date().toISOString();
@@ -193,7 +193,6 @@ async function readJson(path, schema) {
193
193
  throw new PlanStoreError(`read failed: ${path}`, cause);
194
194
  }
195
195
  }
196
- // ─── PlanStore ──────────────────────────────────────────────────────────
197
196
  export class PlanStore {
198
197
  root;
199
198
  autoSync = false;
@@ -230,16 +229,15 @@ export class PlanStore {
230
229
  async runBatchForMigration(fn) {
231
230
  return this.runAsBatch(fn);
232
231
  }
232
+ /** Public batch wrapper: suspend autoSync (status rollup) for a sequence of
233
+ * writes. Use for priority-only reorders so they don't recompute phase/feature
234
+ * status (a reorder must not flip a partially-done feature to in-progress). */
235
+ async runBatch(fn) {
236
+ return this.runAsBatch(fn);
237
+ }
233
238
  async maybeAutoSync() {
234
- if (!this.autoSync || this.syncGuard || this.batchInProgress)
235
- return;
236
- try {
237
- this.syncGuard = true;
238
- await this.syncStatuses();
239
- }
240
- finally {
241
- this.syncGuard = false;
242
- }
239
+ // No-op: status is derived on read, so there is nothing to sync after a
240
+ // save. Kept so existing save* call sites compile unchanged.
243
241
  }
244
242
  normalizeTasks(tasks) {
245
243
  let changed = false;
@@ -484,12 +482,19 @@ export class PlanStore {
484
482
  "- `schema/plan.schema.json` — JSON Schema for tooling",
485
483
  ].join("\n");
486
484
  await writeFile(join(this.root, "README.md"), readme, "utf-8");
487
- // Write a .gitignore inside .planner/ so transient backup/tmp files are
485
+ // Write a .gitignore inside .planner/ so transient/derived files are
488
486
  // not tracked by the host project's git. Git respects nested .gitignore.
487
+ // - *.bak/*.tmp.*: crash backups from atomic writes
488
+ // - resume.json: per-session resume focus + the machine-local guard-bypass
489
+ // timestamp (guardBypassUntil must NOT leak into git/other clones)
490
+ // - generated/: auto-regenerated markdown views (derived from JSON; churn)
489
491
  await writeFile(join(this.root, ".gitignore"), [
490
- "# Agent Plan transient files — do not track",
492
+ "# Agent Plan transient/derived files — do not track",
491
493
  "*.bak",
492
494
  "*.tmp.*",
495
+ "resume.json",
496
+ "resume.*.json",
497
+ "generated/",
493
498
  "",
494
499
  ].join("\n"), "utf-8");
495
500
  }
@@ -510,11 +515,14 @@ export class PlanStore {
510
515
  return readJson(this.projectPath(), ProjectSchema);
511
516
  }
512
517
  async loadPhase(phaseId) {
513
- const phase = await readJson(this.phasePath(phaseId), PhaseSchema);
514
- return this.normalizePhaseDocument(phase).phase;
515
- }
516
- async loadFeatures() {
517
- // Per-file layout: read features/<id>.json (one file per feature).
518
+ const raw = await readJson(this.phasePath(phaseId), PhaseSchema);
519
+ const normalized = this.normalizePhaseDocument(raw).phase;
520
+ return { ...normalized, status: this.derivePhaseStatus(normalized.tasks) };
521
+ }
522
+ /** Read raw feature files WITHOUT the derived `status` field. Used
523
+ * internally so loadFeatures/loadAll can derive status from phases without
524
+ * double-loading. */
525
+ async loadRawFeatures() {
518
526
  let jsonFiles = [];
519
527
  try {
520
528
  const all = await readdir(this.featuresDir());
@@ -524,28 +532,41 @@ export class PlanStore {
524
532
  // features/ absent → fall through to legacy single-file layout
525
533
  }
526
534
  if (jsonFiles.length > 0) {
527
- const features = [];
535
+ const out = [];
528
536
  for (const f of jsonFiles) {
529
537
  const id = f.replace(/\.json$/, "");
530
538
  try {
531
- features.push(await readJson(this.featurePath(id), FeatureSchema));
539
+ out.push(await readJson(this.featurePath(id), FeatureSchema));
532
540
  }
533
541
  catch (err) {
534
542
  // Skip an invalid feature file rather than failing the whole load.
535
543
  console.warn(`[plan-store] skipping invalid feature file ${f}:`, err);
536
544
  }
537
545
  }
538
- return this.normalizeFeaturesDocument({ features }).doc;
546
+ // Deterministic order: sort by the persisted `number` (creation order)
547
+ // so callers that renumber by index (normalizeFeaturesDocument) and
548
+ // callers that keep persisted numbers (loadAll) agree, regardless of the
549
+ // filesystem readdir order. Tiebreak by id for full determinism.
550
+ out.sort((a, b) => (a.number - b.number) || a.id.localeCompare(b.id));
551
+ return out;
539
552
  }
540
553
  // Legacy: single features.json (pre-migration read; migration writes on first write op).
541
554
  try {
542
555
  const legacy = await readJson(this.featuresPath(), FeaturesDocumentSchema);
543
- return this.normalizeFeaturesDocument(legacy).doc;
556
+ const legacyFeatures = legacy.features;
557
+ legacyFeatures.sort((a, b) => (a.number - b.number) || a.id.localeCompare(b.id));
558
+ return legacyFeatures;
544
559
  }
545
560
  catch {
546
- return { features: [] };
561
+ return [];
547
562
  }
548
563
  }
564
+ async loadFeatures() {
565
+ const raws = await this.loadRawFeatures();
566
+ const phases = await this.loadAllPhases();
567
+ const features = raws.map((f) => ({ ...f, status: this.deriveFeatureStatus(f.id, phases) }));
568
+ return this.normalizeFeaturesDocument({ features }).doc;
569
+ }
549
570
  async loadCodebaseProfile() {
550
571
  try {
551
572
  return await readJson(this.codebasePath(), CodebaseProfileSchema);
@@ -731,14 +752,15 @@ export class PlanStore {
731
752
  });
732
753
  }
733
754
  async loadAll() {
734
- const [manifest, project, features, requirements, phases] = await Promise.all([
755
+ const [manifest, project, requirements, phases] = await Promise.all([
735
756
  this.loadManifest(),
736
757
  this.loadProject(),
737
- this.loadFeatures(),
738
758
  this.loadRequirements(),
739
759
  this.loadAllPhases(),
740
760
  ]);
741
- return PlanWorkspaceSchema.parse({ manifest, project, features, requirements, phases });
761
+ const rawFeatures = await this.loadRawFeatures();
762
+ const features = rawFeatures.map((f) => ({ ...f, status: this.deriveFeatureStatus(f.id, phases) }));
763
+ return { manifest, project, requirements, phases, features: { features } };
742
764
  }
743
765
  /** Migrate legacy non-feature-scoped phase ids to feature-scoped ids and repair
744
766
  * dangling feature.phaseIds references. Idempotent. */
@@ -1042,123 +1064,77 @@ export class PlanStore {
1042
1064
  const duplicateShortIds = [...sidCounts.entries()].filter(([, c]) => c > 1).map(([id]) => id);
1043
1065
  return { duplicatePhaseIds, danglingPhaseIds, duplicateShortIds };
1044
1066
  }
1045
- derivePhaseStatus(phase) {
1046
- if (phase.tasks.length === 0)
1047
- return phase.status;
1048
- const taskStatuses = phase.tasks.map((task) => task.status);
1049
- const allRejectedOrCanceled = taskStatuses.every((status) => status === "rejected" || status === "canceled");
1050
- const anyBlocked = taskStatuses.some((status) => status === "blocked");
1051
- const anyInProgress = taskStatuses.some((status) => status === "in-progress");
1052
- const anyWaiting = taskStatuses.some((status) => status === "waiting");
1053
- const anyDeferred = taskStatuses.some((status) => status === "deferred");
1054
- const anyPlanned = taskStatuses.some((status) => status === "planned");
1055
- const anyDone = taskStatuses.some((status) => status === "done");
1056
- if (allRejectedOrCanceled)
1067
+ derivePhaseStatus(tasks) {
1068
+ if (tasks.length === 0)
1069
+ return "draft";
1070
+ const taskStatuses = tasks.map((task) => task.status);
1071
+ // Ignore rejected/canceled tasks (void) when deriving progress.
1072
+ const meaningful = taskStatuses.filter((s) => s !== "rejected" && s !== "canceled");
1073
+ if (meaningful.length === 0)
1057
1074
  return "rejected";
1058
- if (anyBlocked)
1059
- return "blocked";
1060
- if (anyInProgress)
1075
+ if (meaningful.every((s) => s === "done"))
1076
+ return "done";
1077
+ // Lifecycle truth: any progress (active work OR partial completion)
1078
+ // in-progress, until fully done. This is what prevents a single
1079
+ // blocked/waiting/deferred task from poisoning the parent when there is
1080
+ // substantial done or in-progress work (the long-standing rollup bug).
1081
+ if (meaningful.some((s) => s === "in-progress") || meaningful.some((s) => s === "done"))
1061
1082
  return "in-progress";
1062
- if (anyWaiting)
1083
+ // No progress at all ⇒ surface the stall / not-started state (blocked > waiting > deferred > planned).
1084
+ if (meaningful.some((s) => s === "blocked"))
1085
+ return "blocked";
1086
+ if (meaningful.some((s) => s === "waiting"))
1063
1087
  return "waiting";
1064
- if (anyDeferred)
1088
+ if (meaningful.some((s) => s === "deferred"))
1065
1089
  return "deferred";
1066
- if (anyPlanned)
1067
- return "planned";
1068
- if (anyDone)
1069
- return "done";
1070
1090
  return "planned";
1071
1091
  }
1072
- deriveFeatureStatus(featureId, currentStatus, phases) {
1092
+ deriveFeatureStatus(featureId, phases) {
1073
1093
  const featurePhases = phases.filter((phase) => phase.featureId === featureId);
1074
1094
  if (featurePhases.length === 0)
1075
- return currentStatus;
1095
+ return "planned";
1076
1096
  const phaseStatuses = featurePhases.map((phase) => phase.status);
1077
- const allRejectedOrCanceled = phaseStatuses.every((status) => status === "rejected" || status === "canceled");
1078
- const anyBlocked = phaseStatuses.some((status) => status === "blocked");
1079
- const anyActive = phaseStatuses.some((status) => status === "discovery" || status === "in-progress");
1080
- const anyWaiting = phaseStatuses.some((status) => status === "waiting");
1081
- const anyDeferred = phaseStatuses.some((status) => status === "deferred");
1082
- const anyPlannedLike = phaseStatuses.some((status) => status === "draft" || status === "planned");
1083
- const anyDone = phaseStatuses.every((status) => status === "done");
1084
- if (allRejectedOrCanceled)
1097
+ // Ignore rejected/canceled phases when deriving progress.
1098
+ const meaningful = phaseStatuses.filter((s) => s !== "rejected" && s !== "canceled");
1099
+ if (meaningful.length === 0)
1085
1100
  return "rejected";
1086
- if (anyBlocked)
1087
- return "blocked";
1088
- if (anyActive)
1101
+ if (meaningful.every((s) => s === "done"))
1102
+ return "done";
1103
+ // Any progress (an active phase, or a partially-complete done phase)
1104
+ // in-progress. Prevents a single stalled phase from poisoning the feature
1105
+ // when other phases have done/in-progress work.
1106
+ if (meaningful.some((s) => s === "discovery" || s === "in-progress") || meaningful.some((s) => s === "done"))
1089
1107
  return "in-progress";
1090
- if (anyWaiting)
1108
+ // No progress at all ⇒ surface the stall / not-started state.
1109
+ if (meaningful.some((s) => s === "blocked"))
1110
+ return "blocked";
1111
+ if (meaningful.some((s) => s === "waiting"))
1091
1112
  return "waiting";
1092
- if (anyDeferred)
1113
+ if (meaningful.some((s) => s === "deferred"))
1093
1114
  return "deferred";
1094
- if (anyPlannedLike)
1095
- return "planned";
1096
- if (anyDone)
1097
- return "done";
1098
1115
  return "planned";
1099
1116
  }
1100
1117
  async syncStatuses() {
1101
- // Run as a batch so the internal saveFeatures + N savePhase calls do not
1102
- // re-trigger syncStatuses on every write (O(N^2) on large planners).
1103
- // Returns the composite refs of phases whose handoff was auto-cleared
1104
- // (phase transitioned to done).
1105
- const cleared = [];
1106
- await this.runAsBatch(async () => {
1107
- await this.migratePhaseIds();
1108
- const workspace = await this.loadAll();
1109
- const { phases, features } = workspace;
1110
- const featNum = new Map(features.features.map((f) => [f.id, f.number]));
1111
- // 1. Update Phase statuses based on tasks; auto-clear handoff when a
1112
- // phase transitions to done (completed phases don't keep stale
1113
- // handoffs). handoffUpdatedAt is kept as an audit trail.
1114
- for (const phase of phases) {
1115
- const was = phase.status;
1116
- phase.status = this.derivePhaseStatus(phase);
1117
- if (phase.status === "done" && was !== "done" && phase.handoff) {
1118
- phase.handoff = "";
1119
- cleared.push(formatPhaseRef(phase.number, featNum.get(phase.featureId ?? "")));
1120
- }
1121
- }
1122
- // 2. Update Feature statuses based on phases
1123
- for (const feature of features.features) {
1124
- feature.status = this.deriveFeatureStatus(feature.id, feature.status, phases);
1125
- }
1126
- // 3. Save everything
1127
- await this.saveFeatures(features);
1128
- for (const phase of phases) {
1129
- await this.savePhase(phase);
1130
- }
1131
- // 4. Refresh resume focus so a subentrating agent sees current state
1132
- await this.refreshResume();
1133
- });
1134
- return cleared;
1135
- }
1136
- /** Optimized rollup: syncs only the affected phase and its parent feature.
1137
- * Drastically reduces write operations and 'busy' window for task updates.
1138
- * Returns the composite ref of the phase if its handoff was auto-cleared
1139
- * (phase transitioned to done), else null. */
1118
+ // No-op: phase/feature status is now DERIVED at read time (never persisted),
1119
+ // so there is nothing to sync. Kept for backward compatibility with callers
1120
+ // (serve.ts, adapters) that invoke it after mutations.
1121
+ return [];
1122
+ }
1123
+ /** Auto-clear a phase's handoff when its DERIVED status is done. Status itself
1124
+ * is no longer persisted (derived on read), so the only remaining side effect
1125
+ * of a task→done transition is clearing a stale handoff on a completed phase.
1126
+ * Returns the composite ref of the phase if its handoff was cleared, else null. */
1140
1127
  async syncTaskStatusRollup(phaseId) {
1141
1128
  const phase = await this.loadPhase(phaseId);
1142
- const was = phase.status;
1143
- phase.status = this.derivePhaseStatus(phase);
1144
- // Auto-clear handoff when the phase transitions to done.
1145
- const cleared = phase.status === "done" && was !== "done" && phase.handoff !== "";
1146
- if (cleared)
1147
- phase.handoff = "";
1148
- await this.savePhase(phase);
1149
- let feature;
1150
- if (phase.featureId) {
1151
- const featuresDoc = await this.loadFeatures();
1152
- feature = featuresDoc.features.find((f) => f.id === phase.featureId);
1153
- if (feature) {
1154
- // To derive feature status, we still need the statuses of all its phases
1155
- const allPhases = await this.loadAllPhases();
1156
- feature.status = this.deriveFeatureStatus(feature.id, feature.status, allPhases);
1157
- await this.saveFeatures(featuresDoc);
1158
- }
1129
+ let cleared = null;
1130
+ if (phase.status === "done" && phase.handoff !== "") {
1131
+ await this.updatePhase(phaseId, (p) => ({ ...p, handoff: "", handoffUpdatedAt: nowISO() }));
1132
+ const features = await this.loadFeatures();
1133
+ const feature = features.features.find((f) => f.id === phase.featureId);
1134
+ cleared = formatPhaseRef(phase.number, feature?.number);
1159
1135
  }
1160
1136
  await this.refreshResume();
1161
- return cleared ? formatPhaseRef(phase.number, feature?.number) : null;
1137
+ return cleared;
1162
1138
  }
1163
1139
  // ── Savers ───────────────────────────────────────────────────────────
1164
1140
  async updateProject(updater) {
@@ -1247,9 +1223,17 @@ export class PlanStore {
1247
1223
  * task_create / phase_update calls on the SAME phaseId so batch operations
1248
1224
  * don't lose tasks (last-write-wins race condition). */
1249
1225
  async updatePhase(phaseId, updater) {
1250
- const updated = await atomicUpdateJson(this.phasePath(phaseId), PhaseSchema, (phase) => this.normalizePhaseDocument(updater(phase)).phase);
1226
+ // Augment the raw (on-disk) phase with its DERIVED status before handing it
1227
+ // to the updater, so updaters that read 'phase.status' see the truth. The
1228
+ // returned object's 'status' is stripped by PhaseSchema.parse (status is
1229
+ // not persisted); the return value is re-derived for the caller.
1230
+ const raw = await atomicUpdateJson(this.phasePath(phaseId), PhaseSchema, (rawPhase) => {
1231
+ const current = { ...rawPhase, status: this.derivePhaseStatus(rawPhase.tasks) };
1232
+ const next = updater(current);
1233
+ return this.normalizePhaseDocument(next).phase;
1234
+ });
1251
1235
  await this.maybeAutoSync();
1252
- return updated;
1236
+ return { ...raw, status: this.derivePhaseStatus(raw.tasks) };
1253
1237
  }
1254
1238
  // ── Phase-scoped handoff (entity field, harness-agnostic) ────────────
1255
1239
  /** Get the handoff text for a phase ("" if none). Throws if phase missing. */
@@ -0,0 +1,32 @@
1
+ import type { PlanStore } from "./plan-store.js";
2
+ /**
3
+ * Web UI info for the recap (harness-agnostic — no module globals).
4
+ * Pass { localUrl, lanUrl, port } from whichever harness runs the server.
5
+ * Omit/empty → the recap notes the dashboard is not running.
6
+ */
7
+ export interface RecapWebInfo {
8
+ localUrl?: string | undefined;
9
+ lanUrl?: string | undefined;
10
+ port?: number | undefined;
11
+ }
12
+ /** Which harness is presenting the recap — drives command-name hints. */
13
+ export type RecapHarness = "pi" | "mcp";
14
+ export interface RecapOptions {
15
+ harness?: RecapHarness;
16
+ }
17
+ /**
18
+ * Build a consolidated planner recap (project state + active focus + pending
19
+ * handoffs + web URL). SHARED across all harnesses (Pi command, Pi tool,
20
+ * Claude Code/Codex MCP) so every adapter presents identical content.
21
+ *
22
+ * English by default; Italian if project.chatLanguage is set to Italian.
23
+ * Uses human-readable names/titles plus composite IDs (F00x / P00x(F00x) / T00x)
24
+ * so the user/agent can reference entities unambiguously.
25
+ *
26
+ * Pass opts.harness to get harness-correct command hints in the actionable
27
+ * lines (e.g. "/planner task start" in Pi vs "planner-task-start" in MCP).
28
+ * When the plan is fully complete, stale resume.nextSteps are suppressed and a
29
+ * "plan complete — add a feature/phase to continue" hint is shown instead.
30
+ */
31
+ export declare function buildRecap(st: PlanStore, web?: RecapWebInfo, opts?: RecapOptions): Promise<string>;
32
+ //# sourceMappingURL=recap.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recap.d.ts","sourceRoot":"","sources":["../src/recap.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAGjD;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC3B;AAED,yEAAyE;AACzE,MAAM,MAAM,YAAY,GAAG,IAAI,GAAG,KAAK,CAAC;AAExC,MAAM,WAAW,YAAY;IAC3B,OAAO,CAAC,EAAE,YAAY,CAAC;CACxB;AAKD;;;;;;;;;;;;;GAaG;AACH,wBAAsB,UAAU,CAAC,EAAE,EAAE,SAAS,EAAE,GAAG,GAAE,YAAiB,EAAE,IAAI,GAAE,YAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,CA+GhH"}
package/dist/recap.js ADDED
@@ -0,0 +1,105 @@
1
+ import { formatPhaseRef, formatTwoDigitNumber } from "./naming.js";
2
+ const fref = (n) => `F${formatTwoDigitNumber(n)}`;
3
+ const tref = (n) => `T${formatTwoDigitNumber(n)}`;
4
+ /**
5
+ * Build a consolidated planner recap (project state + active focus + pending
6
+ * handoffs + web URL). SHARED across all harnesses (Pi command, Pi tool,
7
+ * Claude Code/Codex MCP) so every adapter presents identical content.
8
+ *
9
+ * English by default; Italian if project.chatLanguage is set to Italian.
10
+ * Uses human-readable names/titles plus composite IDs (F00x / P00x(F00x) / T00x)
11
+ * so the user/agent can reference entities unambiguously.
12
+ *
13
+ * Pass opts.harness to get harness-correct command hints in the actionable
14
+ * lines (e.g. "/planner task start" in Pi vs "planner-task-start" in MCP).
15
+ * When the plan is fully complete, stale resume.nextSteps are suppressed and a
16
+ * "plan complete — add a feature/phase to continue" hint is shown instead.
17
+ */
18
+ export async function buildRecap(st, web = {}, opts = {}) {
19
+ const [plan, resume, handoffs] = await Promise.all([
20
+ st.loadAll(),
21
+ st.loadResume().catch(() => null),
22
+ st.listHandoffs(),
23
+ ]);
24
+ const feats = plan.features.features;
25
+ const phases = plan.phases;
26
+ const allTasks = phases.flatMap((p) => p.tasks.map((task) => ({ phase: p, task })));
27
+ const totalF = feats.length;
28
+ const doneF = feats.filter((x) => x.status === "done").length;
29
+ const activeF = feats.filter((x) => x.status === "in-progress").length;
30
+ const totalP = phases.length;
31
+ const doneP = phases.filter((x) => x.status === "done").length;
32
+ const activeP = phases.filter((x) => x.status === "in-progress" || x.status === "discovery").length;
33
+ const totalT = allTasks.length;
34
+ const doneT = allTasks.filter(({ task }) => task.status === "done").length;
35
+ const activeT = allTasks.filter(({ task }) => task.status === "in-progress").length;
36
+ // Plan is fully complete: there is work and all of it is done, nothing active.
37
+ // (totalT > 0 guards the empty/unstarted case from looking "complete".)
38
+ const planComplete = totalT > 0 && doneT === totalT && doneP === totalP && doneF === totalF;
39
+ // Current focus = first in-progress task (and its phase/feature).
40
+ const focusTask = allTasks.find(({ task }) => task.status === "in-progress");
41
+ const focusPhase = focusTask?.phase;
42
+ const focusFeature = focusPhase ? feats.find((x) => x.id === focusPhase.featureId) : undefined;
43
+ const italian = (plan.project.chatLanguage || "").toLowerCase().includes("ital");
44
+ // Harness-aware command names for actionable hints.
45
+ const isPi = opts.harness === "pi";
46
+ const cmd = (piCmd, mcpCmd) => (isPi ? piCmd : mcpCmd);
47
+ const taskAddCmd = cmd("/planner task add", "planner-task-add");
48
+ const taskStartCmd = cmd("/planner task start", "planner-task-start");
49
+ const featureAddCmd = cmd("/planner feature add", "planner-feature-add");
50
+ const phaseAddCmd = cmd("/planner phase add", "planner-phase-add");
51
+ const handoffShowCmd = cmd("/planner handoff show", "planner-handoff-show");
52
+ const handoffClearCmd = cmd("/planner handoff clear", "planner-handoff-clear");
53
+ const lines = [];
54
+ lines.push(italian ? "## Ripresa planner" : "## Planner recap");
55
+ const name = plan.project.name || "(unnamed project)";
56
+ lines.push(`${italian ? "Progetto" : "Project"}: ${name}${plan.project.goal ? " — " + plan.project.goal : ""}`);
57
+ lines.push(italian
58
+ ? `Avanzamento: feature ${doneF}/${totalF} completate (${activeF} attive) · fasi ${doneP}/${totalP} completate (${activeP} attive) · task ${doneT}/${totalT} completati (${activeT} attivi)`
59
+ : `Progress: Features ${doneF}/${totalF} done (${activeF} active) · Phases ${doneP}/${totalP} done (${activeP} active) · Tasks ${doneT}/${totalT} done (${activeT} active)`);
60
+ if (focusTask && focusPhase) {
61
+ const fr = focusFeature ? fref(focusFeature.number) : "?";
62
+ const pr = formatPhaseRef(focusPhase.number, focusFeature?.number);
63
+ const tr = tref(focusTask.task.number);
64
+ lines.push(`${italian ? "Focus corrente" : "Current focus"}: ${fr} — ${focusFeature?.name ?? "?"} / ${pr} — ${focusPhase.title} / ${tr} — ${focusTask.task.title} (in-progress)`);
65
+ }
66
+ else if (planComplete) {
67
+ lines.push(italian
68
+ ? "Focus corrente: piano completo — tutte le feature/fasi/task sono concluse."
69
+ : "Current focus: plan complete — all features/phases/tasks are done.");
70
+ }
71
+ else {
72
+ lines.push(`${italian ? "Focus corrente" : "Current focus"}: ${italian ? "nessun task attivo — rivedi il piano e scegli il prossimo task concreto" : "no active task — review the plan and pick the next concrete task"}`);
73
+ }
74
+ // Next step: only surface resume.nextSteps when the plan is NOT complete —
75
+ // otherwise stale init-time steps (e.g. "bootstrap discovery") leak through
76
+ // and contradict an all-done plan.
77
+ if (!planComplete && resume?.nextSteps?.length) {
78
+ lines.push(`${italian ? "Prossimo step" : "Next step"}: ${resume.nextSteps[0]}`);
79
+ }
80
+ if (handoffs.length > 0) {
81
+ lines.push("", italian ? `## Handoff di fase pendenti (${handoffs.length})` : `## Pending phase handoffs (${handoffs.length})`);
82
+ handoffs.forEach((h, i) => lines.push(`[${i + 1}] ${h.compositeRef} — ${h.updatedAt} — "${h.firstLine}"`));
83
+ lines.push("", italian
84
+ ? `→ Leggi quello pertinente con ${handoffShowCmd} <ref> (valida contro lo stato attuale), poi ${handoffClearCmd} <ref> una volta consumato.`
85
+ : `→ Read the relevant one with ${handoffShowCmd} <ref> (validate against current state), then call ${handoffClearCmd} <ref> once consumed (delete-on-resume).`);
86
+ }
87
+ else if (planComplete) {
88
+ lines.push("", italian
89
+ ? `Piano completo — aggiungi una nuova feature (${featureAddCmd}) o fase (${phaseAddCmd}) per continuare.`
90
+ : `Plan complete — add a new feature (${featureAddCmd}) or phase (${phaseAddCmd}) to continue.`);
91
+ }
92
+ else if (activeT === 0) {
93
+ lines.push("", italian
94
+ ? `Nessun handoff pendente e nessun task in-progress. Usa ${taskAddCmd} / ${taskStartCmd} per iniziare.`
95
+ : `No phase handoff pending and no task in-progress. Use ${taskAddCmd} / ${taskStartCmd} to begin work.`);
96
+ }
97
+ if (web.localUrl) {
98
+ lines.push("", italian ? "## Web UI" : "## Web UI", `🌐 Web UI: ${web.localUrl}${web.lanUrl ? " (LAN: " + web.lanUrl + ")" : ""}${web.port ? " (port " + web.port + ")" : ""}`);
99
+ }
100
+ else {
101
+ lines.push("", italian ? "## Web UI" : "## Web UI", `🌐 Web UI: ${italian ? "non attiva — avvia con /planner load" : "not running — start with /planner load"}`);
102
+ }
103
+ lines.push("", italian ? "Vuoi che riprendiamo da qui?" : "Do you want to resume from here?");
104
+ return lines.join("\n");
105
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"refs.d.ts","sourceRoot":"","sources":["../src/refs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAKlD;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,KAAK,EAAE,EACf,QAAQ,EAAE,OAAO,EAAE,EACnB,GAAG,EAAE,MAAM,GACV,KAAK,GAAG,SAAS,CA2BnB"}
1
+ {"version":3,"file":"refs.d.ts","sourceRoot":"","sources":["../src/refs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAKlD;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,KAAK,EAAE,EACf,QAAQ,EAAE,OAAO,EAAE,EACnB,GAAG,EAAE,MAAM,GACV,KAAK,GAAG,SAAS,CAgCnB"}
package/dist/refs.js CHANGED
@@ -31,7 +31,12 @@ export function findPhaseByRef(phases, features, ref) {
31
31
  if (found)
32
32
  return found;
33
33
  }
34
- // 3. Title fallback (backward compatibility with agents using titles)
34
+ // 3. ShortId
35
+ found = phases.find((p) => p.shortId && p.shortId.toLowerCase() === normalized);
36
+ if (found)
37
+ return found;
38
+ // 4. Title fallback (backward compatibility with agents using titles)
39
+ // 5. Title fallback (backward compatibility with agents using titles)
35
40
  return (phases.find((p) => p.title.toLowerCase() === normalized) ??
36
41
  phases.find((p) => p.title.toLowerCase().includes(normalized)));
37
42
  }
package/dist/schema.d.ts CHANGED
@@ -727,7 +727,6 @@ export declare const PhaseSchema: z.ZodObject<{
727
727
  priority: z.ZodDefault<z.ZodNumber>;
728
728
  slug: z.ZodString;
729
729
  title: z.ZodString;
730
- status: z.ZodEnum<["draft", "discovery", "planned", "in-progress", "done", "blocked", "canceled", "rejected", "deferred", "waiting"]>;
731
730
  discussedAt: z.ZodDefault<z.ZodString>;
732
731
  contextReady: z.ZodDefault<z.ZodBoolean>;
733
732
  contextReadyReason: z.ZodDefault<z.ZodString>;
@@ -1052,7 +1051,6 @@ export declare const PhaseSchema: z.ZodObject<{
1052
1051
  handoffUpdatedAt: z.ZodDefault<z.ZodString>;
1053
1052
  }, "strip", z.ZodTypeAny, {
1054
1053
  number: number;
1055
- status: "planned" | "in-progress" | "done" | "blocked" | "canceled" | "rejected" | "deferred" | "waiting" | "draft" | "discovery";
1056
1054
  dependencies: string[];
1057
1055
  updatedAt: string;
1058
1056
  notes: string;
@@ -1135,7 +1133,6 @@ export declare const PhaseSchema: z.ZodObject<{
1135
1133
  featureId?: string | undefined;
1136
1134
  }, {
1137
1135
  number: number;
1138
- status: "planned" | "in-progress" | "done" | "blocked" | "canceled" | "rejected" | "deferred" | "waiting" | "draft" | "discovery";
1139
1136
  updatedAt: string;
1140
1137
  id: string;
1141
1138
  createdAt: string;
@@ -1224,7 +1221,6 @@ export declare const FeatureSchema: z.ZodObject<{
1224
1221
  priority: z.ZodDefault<z.ZodNumber>;
1225
1222
  name: z.ZodString;
1226
1223
  description: z.ZodDefault<z.ZodString>;
1227
- status: z.ZodEnum<["planned", "in-progress", "done", "blocked", "canceled", "rejected", "deferred", "waiting"]>;
1228
1224
  discussedAt: z.ZodDefault<z.ZodString>;
1229
1225
  contextReady: z.ZodDefault<z.ZodBoolean>;
1230
1226
  contextReadyReason: z.ZodDefault<z.ZodString>;
@@ -1260,7 +1256,6 @@ export declare const FeatureSchema: z.ZodObject<{
1260
1256
  updatedAt: z.ZodString;
1261
1257
  }, "strip", z.ZodTypeAny, {
1262
1258
  number: number;
1263
- status: "planned" | "in-progress" | "done" | "blocked" | "canceled" | "rejected" | "deferred" | "waiting";
1264
1259
  name: string;
1265
1260
  updatedAt: string;
1266
1261
  id: string;
@@ -1286,7 +1281,6 @@ export declare const FeatureSchema: z.ZodObject<{
1286
1281
  workRemaining: string;
1287
1282
  phaseIds: string[];
1288
1283
  }, {
1289
- status: "planned" | "in-progress" | "done" | "blocked" | "canceled" | "rejected" | "deferred" | "waiting";
1290
1284
  name: string;
1291
1285
  updatedAt: string;
1292
1286
  id: string;
@@ -1321,7 +1315,6 @@ export declare const FeaturesDocumentSchema: z.ZodObject<{
1321
1315
  priority: z.ZodDefault<z.ZodNumber>;
1322
1316
  name: z.ZodString;
1323
1317
  description: z.ZodDefault<z.ZodString>;
1324
- status: z.ZodEnum<["planned", "in-progress", "done", "blocked", "canceled", "rejected", "deferred", "waiting"]>;
1325
1318
  discussedAt: z.ZodDefault<z.ZodString>;
1326
1319
  contextReady: z.ZodDefault<z.ZodBoolean>;
1327
1320
  contextReadyReason: z.ZodDefault<z.ZodString>;
@@ -1357,7 +1350,6 @@ export declare const FeaturesDocumentSchema: z.ZodObject<{
1357
1350
  updatedAt: z.ZodString;
1358
1351
  }, "strip", z.ZodTypeAny, {
1359
1352
  number: number;
1360
- status: "planned" | "in-progress" | "done" | "blocked" | "canceled" | "rejected" | "deferred" | "waiting";
1361
1353
  name: string;
1362
1354
  updatedAt: string;
1363
1355
  id: string;
@@ -1383,7 +1375,6 @@ export declare const FeaturesDocumentSchema: z.ZodObject<{
1383
1375
  workRemaining: string;
1384
1376
  phaseIds: string[];
1385
1377
  }, {
1386
- status: "planned" | "in-progress" | "done" | "blocked" | "canceled" | "rejected" | "deferred" | "waiting";
1387
1378
  name: string;
1388
1379
  updatedAt: string;
1389
1380
  id: string;
@@ -1413,7 +1404,6 @@ export declare const FeaturesDocumentSchema: z.ZodObject<{
1413
1404
  }, "strip", z.ZodTypeAny, {
1414
1405
  features: {
1415
1406
  number: number;
1416
- status: "planned" | "in-progress" | "done" | "blocked" | "canceled" | "rejected" | "deferred" | "waiting";
1417
1407
  name: string;
1418
1408
  updatedAt: string;
1419
1409
  id: string;
@@ -1441,7 +1431,6 @@ export declare const FeaturesDocumentSchema: z.ZodObject<{
1441
1431
  }[];
1442
1432
  }, {
1443
1433
  features: {
1444
- status: "planned" | "in-progress" | "done" | "blocked" | "canceled" | "rejected" | "deferred" | "waiting";
1445
1434
  name: string;
1446
1435
  updatedAt: string;
1447
1436
  id: string;
@@ -1784,7 +1773,6 @@ export declare const PlanWorkspaceSchema: z.ZodObject<{
1784
1773
  priority: z.ZodDefault<z.ZodNumber>;
1785
1774
  name: z.ZodString;
1786
1775
  description: z.ZodDefault<z.ZodString>;
1787
- status: z.ZodEnum<["planned", "in-progress", "done", "blocked", "canceled", "rejected", "deferred", "waiting"]>;
1788
1776
  discussedAt: z.ZodDefault<z.ZodString>;
1789
1777
  contextReady: z.ZodDefault<z.ZodBoolean>;
1790
1778
  contextReadyReason: z.ZodDefault<z.ZodString>;
@@ -1820,7 +1808,6 @@ export declare const PlanWorkspaceSchema: z.ZodObject<{
1820
1808
  updatedAt: z.ZodString;
1821
1809
  }, "strip", z.ZodTypeAny, {
1822
1810
  number: number;
1823
- status: "planned" | "in-progress" | "done" | "blocked" | "canceled" | "rejected" | "deferred" | "waiting";
1824
1811
  name: string;
1825
1812
  updatedAt: string;
1826
1813
  id: string;
@@ -1846,7 +1833,6 @@ export declare const PlanWorkspaceSchema: z.ZodObject<{
1846
1833
  workRemaining: string;
1847
1834
  phaseIds: string[];
1848
1835
  }, {
1849
- status: "planned" | "in-progress" | "done" | "blocked" | "canceled" | "rejected" | "deferred" | "waiting";
1850
1836
  name: string;
1851
1837
  updatedAt: string;
1852
1838
  id: string;
@@ -1876,7 +1862,6 @@ export declare const PlanWorkspaceSchema: z.ZodObject<{
1876
1862
  }, "strip", z.ZodTypeAny, {
1877
1863
  features: {
1878
1864
  number: number;
1879
- status: "planned" | "in-progress" | "done" | "blocked" | "canceled" | "rejected" | "deferred" | "waiting";
1880
1865
  name: string;
1881
1866
  updatedAt: string;
1882
1867
  id: string;
@@ -1904,7 +1889,6 @@ export declare const PlanWorkspaceSchema: z.ZodObject<{
1904
1889
  }[];
1905
1890
  }, {
1906
1891
  features: {
1907
- status: "planned" | "in-progress" | "done" | "blocked" | "canceled" | "rejected" | "deferred" | "waiting";
1908
1892
  name: string;
1909
1893
  updatedAt: string;
1910
1894
  id: string;
@@ -2041,7 +2025,6 @@ export declare const PlanWorkspaceSchema: z.ZodObject<{
2041
2025
  priority: z.ZodDefault<z.ZodNumber>;
2042
2026
  slug: z.ZodString;
2043
2027
  title: z.ZodString;
2044
- status: z.ZodEnum<["draft", "discovery", "planned", "in-progress", "done", "blocked", "canceled", "rejected", "deferred", "waiting"]>;
2045
2028
  discussedAt: z.ZodDefault<z.ZodString>;
2046
2029
  contextReady: z.ZodDefault<z.ZodBoolean>;
2047
2030
  contextReadyReason: z.ZodDefault<z.ZodString>;
@@ -2366,7 +2349,6 @@ export declare const PlanWorkspaceSchema: z.ZodObject<{
2366
2349
  handoffUpdatedAt: z.ZodDefault<z.ZodString>;
2367
2350
  }, "strip", z.ZodTypeAny, {
2368
2351
  number: number;
2369
- status: "planned" | "in-progress" | "done" | "blocked" | "canceled" | "rejected" | "deferred" | "waiting" | "draft" | "discovery";
2370
2352
  dependencies: string[];
2371
2353
  updatedAt: string;
2372
2354
  notes: string;
@@ -2449,7 +2431,6 @@ export declare const PlanWorkspaceSchema: z.ZodObject<{
2449
2431
  featureId?: string | undefined;
2450
2432
  }, {
2451
2433
  number: number;
2452
- status: "planned" | "in-progress" | "done" | "blocked" | "canceled" | "rejected" | "deferred" | "waiting" | "draft" | "discovery";
2453
2434
  updatedAt: string;
2454
2435
  id: string;
2455
2436
  createdAt: string;
@@ -2535,7 +2516,6 @@ export declare const PlanWorkspaceSchema: z.ZodObject<{
2535
2516
  features: {
2536
2517
  features: {
2537
2518
  number: number;
2538
- status: "planned" | "in-progress" | "done" | "blocked" | "canceled" | "rejected" | "deferred" | "waiting";
2539
2519
  name: string;
2540
2520
  updatedAt: string;
2541
2521
  id: string;
@@ -2617,7 +2597,6 @@ export declare const PlanWorkspaceSchema: z.ZodObject<{
2617
2597
  };
2618
2598
  phases: {
2619
2599
  number: number;
2620
- status: "planned" | "in-progress" | "done" | "blocked" | "canceled" | "rejected" | "deferred" | "waiting" | "draft" | "discovery";
2621
2600
  dependencies: string[];
2622
2601
  updatedAt: string;
2623
2602
  notes: string;
@@ -2702,7 +2681,6 @@ export declare const PlanWorkspaceSchema: z.ZodObject<{
2702
2681
  }, {
2703
2682
  features: {
2704
2683
  features: {
2705
- status: "planned" | "in-progress" | "done" | "blocked" | "canceled" | "rejected" | "deferred" | "waiting";
2706
2684
  name: string;
2707
2685
  updatedAt: string;
2708
2686
  id: string;
@@ -2785,7 +2763,6 @@ export declare const PlanWorkspaceSchema: z.ZodObject<{
2785
2763
  };
2786
2764
  phases: {
2787
2765
  number: number;
2788
- status: "planned" | "in-progress" | "done" | "blocked" | "canceled" | "rejected" | "deferred" | "waiting" | "draft" | "discovery";
2789
2766
  updatedAt: string;
2790
2767
  id: string;
2791
2768
  createdAt: string;
@@ -2876,8 +2853,12 @@ export type ActivityEntry = z.infer<typeof ActivityEntrySchema>;
2876
2853
  export type ActivityLog = z.infer<typeof ActivityLogSchema>;
2877
2854
  export type ResumeFocus = z.infer<typeof ResumeFocusSchema>;
2878
2855
  export type FeatureStatus = z.infer<typeof FeatureStatusSchema>;
2879
- export type Feature = z.infer<typeof FeatureSchema>;
2880
- export type FeaturesDocument = z.infer<typeof FeaturesDocumentSchema>;
2856
+ export type Feature = z.infer<typeof FeatureSchema> & {
2857
+ status: FeatureStatus;
2858
+ };
2859
+ export type FeaturesDocument = {
2860
+ features: Feature[];
2861
+ };
2881
2862
  export type PhaseStatus = z.infer<typeof PhaseStatusSchema>;
2882
2863
  export type TaskStatus = z.infer<typeof TaskStatusSchema>;
2883
2864
  export type RequirementStatus = z.infer<typeof RequirementStatusSchema>;
@@ -2890,9 +2871,14 @@ export type Subtask = z.infer<typeof SubtaskSchema>;
2890
2871
  export type ChecklistItem = z.infer<typeof ChecklistItemSchema>;
2891
2872
  export type StatusLogEntry = z.infer<typeof StatusLogEntrySchema>;
2892
2873
  export type Task = z.infer<typeof TaskSchema>;
2893
- export type Phase = z.infer<typeof PhaseSchema>;
2874
+ export type Phase = z.infer<typeof PhaseSchema> & {
2875
+ status: PhaseStatus;
2876
+ };
2894
2877
  export type MacroTask = z.infer<typeof MacroTaskSchema>;
2895
2878
  export type Requirement = z.infer<typeof RequirementSchema>;
2896
2879
  export type RequirementsDocument = z.infer<typeof RequirementsDocumentSchema>;
2897
- export type PlanWorkspace = z.infer<typeof PlanWorkspaceSchema>;
2880
+ export type PlanWorkspace = Omit<z.infer<typeof PlanWorkspaceSchema>, "phases" | "features"> & {
2881
+ phases: Phase[];
2882
+ features: FeaturesDocument;
2883
+ };
2898
2884
  //# sourceMappingURL=schema.d.ts.map
@@ -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
@@ -171,7 +171,9 @@ export const PhaseSchema = z.object({
171
171
  priority: z.number().int().nonnegative().default(0),
172
172
  slug: SlugSchema,
173
173
  title: z.string().min(1),
174
- status: PhaseStatusSchema,
174
+ // NOTE: `status` is intentionally ABSENT from the schema — it is a DERIVED
175
+ // value (computed from child tasks at read time) and is never persisted.
176
+ // The runtime `Phase` type re-adds it as a non-optional field (see below).
175
177
  discussedAt: z.string().default(""),
176
178
  contextReady: z.boolean().default(false),
177
179
  contextReadyReason: z.string().default(""),
@@ -201,7 +203,8 @@ export const FeatureSchema = z.object({
201
203
  priority: z.number().int().nonnegative().default(0),
202
204
  name: z.string().min(1),
203
205
  description: z.string().default(""),
204
- status: FeatureStatusSchema,
206
+ // NOTE: `status` is intentionally ABSENT — it is DERIVED from child phases
207
+ // at read time and never persisted. The runtime `Feature` type re-adds it.
205
208
  discussedAt: z.string().default(""),
206
209
  contextReady: z.boolean().default(false),
207
210
  contextReadyReason: z.string().default(""),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-plan/core",
3
- "version": "0.2.19-next.0",
3
+ "version": "0.2.19-next.2",
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",