@agent-plan/core 0.2.17 → 0.2.19-next.0
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 +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/naming.d.ts +13 -0
- package/dist/naming.d.ts.map +1 -1
- package/dist/naming.js +28 -1
- package/dist/plan-store.d.ts +61 -4
- package/dist/plan-store.d.ts.map +1 -1
- package/dist/plan-store.js +335 -13
- package/dist/refs.d.ts +24 -0
- package/dist/refs.d.ts.map +1 -0
- package/dist/refs.js +37 -0
- package/dist/schema.d.ts +104 -0
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +8 -0
- package/package.json +3 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export * from "./naming.js";
|
|
2
|
+
export * from "./refs.js";
|
|
2
3
|
export * from "./schema.js";
|
|
3
|
-
export { PlanStore, PlanStoreError, setWriteBusyHook, setWriteNotifyHook, migrateToUuids, withFeatureLock } from "./plan-store.js";
|
|
4
|
+
export { PlanStore, PlanStoreError, setWriteBusyHook, setWriteNotifyHook, migrateToUuids, withFeatureLock, type PhaseHandoffSummary } from "./plan-store.js";
|
|
4
5
|
export { PlanRenderer } from "./renderer.js";
|
|
5
6
|
export { ExportService } from "./export-service.js";
|
|
6
7
|
export type { CodebaseProfile, ResumeFocus, ActivityEntry, ActivityLog, AmbientFacts } from "./schema.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,iBAAiB,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,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
package/dist/naming.d.ts
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
/** Crockford Base32 alphabet — excludes ambiguous characters 0/O/1/I/L
|
|
2
|
+
* to minimize human transcription errors. 32 symbols → 5 chars = 33M combos. */
|
|
3
|
+
export declare const CROCKFORD_ALPHABET = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789";
|
|
4
|
+
export declare const SHORT_ID_LENGTH = 5;
|
|
5
|
+
export declare const SHORT_ID_PATTERN: RegExp;
|
|
6
|
+
/** Generate a globally-unique short id (5 chars, Crockford Base32, e.g. `UUXD1`-style
|
|
7
|
+
* but without 0/1/I/O). Retries until the id is not in `existing` (project-scoped
|
|
8
|
+
* collision guard). Throws only in the impossible saturation case (~50 retries). */
|
|
9
|
+
export declare function createShortId(existing?: Set<string>): string;
|
|
1
10
|
export declare function normalizeSlug(input: string): string;
|
|
2
11
|
/** Normalize, truncate to maxLen, and strip dangling dashes so the result
|
|
3
12
|
* always satisfies SlugSchema (/^[a-z0-9]+(?:-[a-z0-9]+)*$/). Returns fallback
|
|
@@ -7,6 +16,10 @@ export declare function normalizeSlug(input: string): string;
|
|
|
7
16
|
export declare function clampSlug(input: string, maxLen?: number, fallback?: string): string;
|
|
8
17
|
export declare function formatTwoDigitNumber(value: number): string;
|
|
9
18
|
export declare function formatThreeDigitNumber(value: number): string;
|
|
19
|
+
/** Human-readable phase composite ref: `P00x` or `P00x(F00x)` when the parent
|
|
20
|
+
* feature number is known. Harness-agnostic (used by core handoff listing +
|
|
21
|
+
* adapters). */
|
|
22
|
+
export declare function formatPhaseRef(phaseNumber: number, featureNumber?: number): string;
|
|
10
23
|
export declare function createPhaseId(): string;
|
|
11
24
|
/** True for legacy phase ids that are NOT feature-scoped (e.g. `phase-01-...`). */
|
|
12
25
|
export declare function isLegacyPhaseId(phaseId: string): boolean;
|
package/dist/naming.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"naming.d.ts","sourceRoot":"","sources":["../src/naming.ts"],"names":[],"mappings":"AAKA,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,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,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
|
@@ -1,6 +1,26 @@
|
|
|
1
|
-
import { randomUUID } from "node:crypto";
|
|
1
|
+
import { randomInt, randomUUID } from "node:crypto";
|
|
2
2
|
const SLUG_PATTERN = /[^a-z0-9]+/g;
|
|
3
3
|
const MULTI_DASH_PATTERN = /-+/g;
|
|
4
|
+
/** Crockford Base32 alphabet — excludes ambiguous characters 0/O/1/I/L
|
|
5
|
+
* to minimize human transcription errors. 32 symbols → 5 chars = 33M combos. */
|
|
6
|
+
export const CROCKFORD_ALPHABET = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789";
|
|
7
|
+
export const SHORT_ID_LENGTH = 5;
|
|
8
|
+
export const SHORT_ID_PATTERN = /^[A-Z2-9]{5}$/;
|
|
9
|
+
/** Generate a globally-unique short id (5 chars, Crockford Base32, e.g. `UUXD1`-style
|
|
10
|
+
* but without 0/1/I/O). Retries until the id is not in `existing` (project-scoped
|
|
11
|
+
* collision guard). Throws only in the impossible saturation case (~50 retries). */
|
|
12
|
+
export function createShortId(existing = new Set()) {
|
|
13
|
+
const max = CROCKFORD_ALPHABET.length;
|
|
14
|
+
for (let attempt = 0; attempt < 64; attempt += 1) {
|
|
15
|
+
let id = "";
|
|
16
|
+
for (let i = 0; i < SHORT_ID_LENGTH; i += 1) {
|
|
17
|
+
id += CROCKFORD_ALPHABET[randomInt(0, max)];
|
|
18
|
+
}
|
|
19
|
+
if (!existing.has(id))
|
|
20
|
+
return id;
|
|
21
|
+
}
|
|
22
|
+
throw new Error("createShortId: could not generate a unique id after 64 attempts");
|
|
23
|
+
}
|
|
4
24
|
export function normalizeSlug(input) {
|
|
5
25
|
return input
|
|
6
26
|
.trim()
|
|
@@ -24,6 +44,13 @@ export function formatTwoDigitNumber(value) {
|
|
|
24
44
|
export function formatThreeDigitNumber(value) {
|
|
25
45
|
return String(value).padStart(3, "0");
|
|
26
46
|
}
|
|
47
|
+
/** Human-readable phase composite ref: `P00x` or `P00x(F00x)` when the parent
|
|
48
|
+
* feature number is known. Harness-agnostic (used by core handoff listing +
|
|
49
|
+
* adapters). */
|
|
50
|
+
export function formatPhaseRef(phaseNumber, featureNumber) {
|
|
51
|
+
const p = `P${formatThreeDigitNumber(phaseNumber)}`;
|
|
52
|
+
return featureNumber != null ? `${p}(F${formatThreeDigitNumber(featureNumber)})` : p;
|
|
53
|
+
}
|
|
27
54
|
export function createPhaseId() {
|
|
28
55
|
return randomUUID();
|
|
29
56
|
}
|
package/dist/plan-store.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type FeaturesDocument, type Manifest, type Phase, type PlanWorkspace, type Project, type RequirementsDocument, type ActivityEntry, type ActivityLog, type CodebaseProfile, type ResumeFocus } from "./schema.js";
|
|
1
|
+
import { type Feature, type FeaturesDocument, type Manifest, type Phase, type PlanWorkspace, type Project, type RequirementsDocument, type ActivityEntry, type ActivityLog, type CodebaseProfile, type ResumeFocus } from "./schema.js";
|
|
2
2
|
export declare class PlanStoreError extends Error {
|
|
3
3
|
readonly cause?: unknown | undefined;
|
|
4
4
|
constructor(message: string, cause?: unknown | undefined);
|
|
@@ -6,6 +6,16 @@ export declare class PlanStoreError extends Error {
|
|
|
6
6
|
export declare function setWriteBusyHook(hook: ((busy: boolean) => void) | undefined): void;
|
|
7
7
|
export declare function setWriteNotifyHook(hook: (() => void) | undefined): void;
|
|
8
8
|
export declare function withFeatureLock<T>(featureId: string, fn: () => Promise<T>): Promise<T>;
|
|
9
|
+
/** Summary of a phase that has a non-empty handoff, for the listHandoffs() API. */
|
|
10
|
+
export interface PhaseHandoffSummary {
|
|
11
|
+
phaseId: string;
|
|
12
|
+
/** Human-readable composite ref, e.g. `P003` or `P003(F002)`. */
|
|
13
|
+
compositeRef: string;
|
|
14
|
+
/** handoffUpdatedAt (falls back to phase.updatedAt if unset). */
|
|
15
|
+
updatedAt: string;
|
|
16
|
+
/** First non-empty line of the handoff, leading markdown headers stripped, ~80 chars. */
|
|
17
|
+
firstLine: string;
|
|
18
|
+
}
|
|
9
19
|
export declare function migrateToUuids(store: PlanStore): Promise<void>;
|
|
10
20
|
export declare class PlanStore {
|
|
11
21
|
readonly root: string;
|
|
@@ -36,6 +46,13 @@ export declare class PlanStore {
|
|
|
36
46
|
private projectPath;
|
|
37
47
|
private requirementsPath;
|
|
38
48
|
private featuresPath;
|
|
49
|
+
private featuresDir;
|
|
50
|
+
private featurePath;
|
|
51
|
+
private withFeaturesLock;
|
|
52
|
+
/** Idempotent one-time migration: if a legacy features.json exists, split it
|
|
53
|
+
* into features/<id>.json (one per feature) and remove the legacy file.
|
|
54
|
+
* Must be called under withFeaturesLock. Crash-safe: re-run overwrites. */
|
|
55
|
+
private migrateLegacy;
|
|
39
56
|
private phasesDir;
|
|
40
57
|
private phasePath;
|
|
41
58
|
private generatedDir;
|
|
@@ -95,6 +112,22 @@ export declare class PlanStore {
|
|
|
95
112
|
cleanupOrphanBackups(): Promise<{
|
|
96
113
|
removed: number;
|
|
97
114
|
}>;
|
|
115
|
+
/** All non-empty shortIds currently assigned in the project (features + phases + tasks).
|
|
116
|
+
* Read-only; used by createShortId collision guard during entity creation. */
|
|
117
|
+
assignedShortIds(): Promise<Set<string>>;
|
|
118
|
+
/** Next priority (>=1) for a new entity within its scope.
|
|
119
|
+
* - feature: max priority among features + 1
|
|
120
|
+
* - phase: max priority among phases of parentId (featureId) + 1
|
|
121
|
+
* - task: max priority among tasks of parentId (phaseId) + 1 */
|
|
122
|
+
nextPriority(kind: "feature" | "phase" | "task", parentId?: string): Promise<number>;
|
|
123
|
+
/** Idempotent backfill of shortId (globally-unique 5-char Crockford) and priority
|
|
124
|
+
* (per-scope display order). Assigns missing shortIds and priorities; never overwrites
|
|
125
|
+
* existing non-empty shortIds or non-zero priorities. Safe to run at startup. */
|
|
126
|
+
ensureShortIdsAndPriority(): Promise<{
|
|
127
|
+
shortIdsAssigned: number;
|
|
128
|
+
prioritiesAssigned: number;
|
|
129
|
+
duplicateShortIds: string[];
|
|
130
|
+
}>;
|
|
98
131
|
/** Repair dangling references and report integrity. One-shot maintenance op. */
|
|
99
132
|
repair(): Promise<{
|
|
100
133
|
migrated: {
|
|
@@ -102,33 +135,57 @@ export declare class PlanStore {
|
|
|
102
135
|
repaired: number;
|
|
103
136
|
inferred: number;
|
|
104
137
|
};
|
|
138
|
+
backfill: {
|
|
139
|
+
shortIdsAssigned: number;
|
|
140
|
+
prioritiesAssigned: number;
|
|
141
|
+
duplicateShortIds: string[];
|
|
142
|
+
};
|
|
105
143
|
integrity: {
|
|
106
144
|
duplicatePhaseIds: string[];
|
|
107
145
|
danglingPhaseIds: string[];
|
|
146
|
+
duplicateShortIds: string[];
|
|
108
147
|
};
|
|
109
148
|
}>;
|
|
110
149
|
/** Validate plan integrity: globally unique phase ids and resolvable feature.phaseIds. */
|
|
111
150
|
validateIntegrity(): Promise<{
|
|
112
151
|
duplicatePhaseIds: string[];
|
|
113
152
|
danglingPhaseIds: string[];
|
|
153
|
+
duplicateShortIds: string[];
|
|
114
154
|
}>;
|
|
115
155
|
private derivePhaseStatus;
|
|
116
156
|
private deriveFeatureStatus;
|
|
117
|
-
syncStatuses(): Promise<
|
|
157
|
+
syncStatuses(): Promise<string[]>;
|
|
118
158
|
/** Optimized rollup: syncs only the affected phase and its parent feature.
|
|
119
|
-
* Drastically reduces write operations and 'busy' window for task updates.
|
|
120
|
-
|
|
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. */
|
|
162
|
+
syncTaskStatusRollup(phaseId: string): Promise<string | null>;
|
|
121
163
|
updateProject(updater: (p: Project) => Project): Promise<Project>;
|
|
122
164
|
updateFeatures(updater: (f: FeaturesDocument) => FeaturesDocument): Promise<FeaturesDocument>;
|
|
123
165
|
updateRequirements(updater: (r: RequirementsDocument) => RequirementsDocument): Promise<RequirementsDocument>;
|
|
124
166
|
saveProject(project: Project): Promise<void>;
|
|
125
167
|
saveFeatures(features: FeaturesDocument): Promise<void>;
|
|
168
|
+
/** Per-file write of all features + orphan reconcile. No lock (caller holds withFeaturesLock). */
|
|
169
|
+
private saveFeaturesRaw;
|
|
170
|
+
/** Granular single-feature write (per-file lock; parallel-safe across features). */
|
|
171
|
+
saveFeature(feature: Feature): Promise<void>;
|
|
126
172
|
saveRequirements(reqs: RequirementsDocument): Promise<void>;
|
|
127
173
|
savePhase(phase: Phase): Promise<void>;
|
|
128
174
|
/** Atomic read-modify-write on a single phase file. Serializes concurrent
|
|
129
175
|
* task_create / phase_update calls on the SAME phaseId so batch operations
|
|
130
176
|
* don't lose tasks (last-write-wins race condition). */
|
|
131
177
|
updatePhase(phaseId: string, updater: (phase: Phase) => Phase): Promise<Phase>;
|
|
178
|
+
/** Get the handoff text for a phase ("" if none). Throws if phase missing. */
|
|
179
|
+
getPhaseHandoff(phaseId: string): Promise<string>;
|
|
180
|
+
/** Set the handoff text for a phase + stamp handoffUpdatedAt. Atomic per-file
|
|
181
|
+
* update via updatePhase (so the web UI refreshes via maybeAutoSync). */
|
|
182
|
+
setPhaseHandoff(phaseId: string, text: string): Promise<void>;
|
|
183
|
+
/** Clear the handoff text for a phase (handoff=""). handoffUpdatedAt is left
|
|
184
|
+
* unchanged as an audit trail (when a handoff last existed). */
|
|
185
|
+
clearPhaseHandoff(phaseId: string): Promise<void>;
|
|
186
|
+
/** List all phases that have a non-empty handoff, newest first, with a
|
|
187
|
+
* human-readable composite ref (P00x or P00x(F00x)) and a first-line excerpt. */
|
|
188
|
+
listHandoffs(): Promise<PhaseHandoffSummary[]>;
|
|
132
189
|
deletePhase(phaseId: string): Promise<void>;
|
|
133
190
|
/** Load the full workspace (manifest + phases + project + requirements + features) */
|
|
134
191
|
loadWorkspace(): Promise<PlanWorkspace>;
|
package/dist/plan-store.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plan-store.d.ts","sourceRoot":"","sources":["../src/plan-store.ts"],"names":[],"mappings":"AAEA,OAAO,
|
|
1
|
+
{"version":3,"file":"plan-store.d.ts","sourceRoot":"","sources":["../src/plan-store.ts"],"names":[],"mappings":"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"}
|
package/dist/plan-store.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { access, copyFile, mkdir, readFile, rename, stat, unlink, writeFile } from "node:fs/promises";
|
|
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, FeaturesDocumentSchema, ManifestSchema, PhaseSchema, PlanWorkspaceSchema, ProjectSchema, RequirementsDocumentSchema, ResumeFocusSchema, ActivityLogSchema, } from "./schema.js";
|
|
4
|
-
import { createFeatureId, createPhaseId, createRequirementId, createTaskId, isLegacyPhaseId } from "./naming.js";
|
|
3
|
+
import { CodebaseProfileSchema, FeatureSchema, FeaturesDocumentSchema, ManifestSchema, PhaseSchema, PlanWorkspaceSchema, ProjectSchema, RequirementsDocumentSchema, ResumeFocusSchema, ActivityLogSchema, } from "./schema.js";
|
|
4
|
+
import { createFeatureId, createPhaseId, createRequirementId, createShortId, createTaskId, formatPhaseRef, isLegacyPhaseId } from "./naming.js";
|
|
5
5
|
function nowISO() {
|
|
6
6
|
return new Date().toISOString();
|
|
7
7
|
}
|
|
@@ -108,6 +108,12 @@ async function atomicUpdateJson(path, schema, updater) {
|
|
|
108
108
|
return parsed;
|
|
109
109
|
});
|
|
110
110
|
}
|
|
111
|
+
/** Extract the first meaningful line of a handoff: skip blank lines, strip a
|
|
112
|
+
* leading markdown header (#), trim, and truncate to ~80 chars. */
|
|
113
|
+
function handoffFirstLine(text) {
|
|
114
|
+
const line = text.trim().split(/\r?\n/).find((l) => l.trim().length > 0) ?? "";
|
|
115
|
+
return line.replace(/^#+\s*/, "").trim().slice(0, 80);
|
|
116
|
+
}
|
|
111
117
|
export async function migrateToUuids(store) {
|
|
112
118
|
// Run as a batch so internal saveFeatures/savePhase calls do not
|
|
113
119
|
// re-trigger syncStatuses (O(N^2) on large planners). Idempotent: if there
|
|
@@ -335,7 +341,7 @@ export class PlanStore {
|
|
|
335
341
|
}
|
|
336
342
|
async ensureStructureOrdering() {
|
|
337
343
|
return this.runAsBatch(async () => {
|
|
338
|
-
const featuresDoc = await
|
|
344
|
+
const featuresDoc = await this.loadFeatures();
|
|
339
345
|
const phases = await this.loadAllPhases();
|
|
340
346
|
const normalized = this.normalizeStructureSnapshot(featuresDoc, phases);
|
|
341
347
|
if (!normalized.changed)
|
|
@@ -360,6 +366,35 @@ export class PlanStore {
|
|
|
360
366
|
featuresPath() {
|
|
361
367
|
return join(this.root, "features.json");
|
|
362
368
|
}
|
|
369
|
+
featuresDir() {
|
|
370
|
+
return join(this.root, "features");
|
|
371
|
+
}
|
|
372
|
+
featurePath(featureId) {
|
|
373
|
+
return join(this.featuresDir(), `${featureId}.json`);
|
|
374
|
+
}
|
|
375
|
+
withFeaturesLock(fn) {
|
|
376
|
+
// Sentinel-keyed mutex (the features dir path) serializing all feature
|
|
377
|
+
// mutations so read-modify-write via updateFeatures is race-free and the
|
|
378
|
+
// one-time legacy→per-file migration never interleaves with a writer.
|
|
379
|
+
return withWriteLock(this.featuresDir(), fn);
|
|
380
|
+
}
|
|
381
|
+
/** Idempotent one-time migration: if a legacy features.json exists, split it
|
|
382
|
+
* into features/<id>.json (one per feature) and remove the legacy file.
|
|
383
|
+
* Must be called under withFeaturesLock. Crash-safe: re-run overwrites. */
|
|
384
|
+
async migrateLegacy() {
|
|
385
|
+
let legacy;
|
|
386
|
+
try {
|
|
387
|
+
legacy = await readJson(this.featuresPath(), FeaturesDocumentSchema);
|
|
388
|
+
}
|
|
389
|
+
catch {
|
|
390
|
+
return; // no legacy features.json (already migrated or fresh project)
|
|
391
|
+
}
|
|
392
|
+
await mkdir(this.featuresDir(), { recursive: true });
|
|
393
|
+
for (const feat of legacy.features) {
|
|
394
|
+
await atomicWriteJson(this.featurePath(feat.id), feat);
|
|
395
|
+
}
|
|
396
|
+
await unlink(this.featuresPath()).catch(() => { });
|
|
397
|
+
}
|
|
363
398
|
phasesDir() {
|
|
364
399
|
return join(this.root, "phases");
|
|
365
400
|
}
|
|
@@ -388,6 +423,7 @@ export class PlanStore {
|
|
|
388
423
|
}
|
|
389
424
|
await mkdir(this.root, { recursive: true });
|
|
390
425
|
await mkdir(this.phasesDir(), { recursive: true });
|
|
426
|
+
await mkdir(this.featuresDir(), { recursive: true });
|
|
391
427
|
await mkdir(join(this.generatedDir(), "phases"), { recursive: true });
|
|
392
428
|
await mkdir(join(this.root, "schema"), { recursive: true });
|
|
393
429
|
await mkdir(join(this.root, "adapters"), { recursive: true });
|
|
@@ -478,9 +514,33 @@ export class PlanStore {
|
|
|
478
514
|
return this.normalizePhaseDocument(phase).phase;
|
|
479
515
|
}
|
|
480
516
|
async loadFeatures() {
|
|
517
|
+
// Per-file layout: read features/<id>.json (one file per feature).
|
|
518
|
+
let jsonFiles = [];
|
|
481
519
|
try {
|
|
482
|
-
const
|
|
483
|
-
|
|
520
|
+
const all = await readdir(this.featuresDir());
|
|
521
|
+
jsonFiles = all.filter((f) => f.endsWith(".json"));
|
|
522
|
+
}
|
|
523
|
+
catch {
|
|
524
|
+
// features/ absent → fall through to legacy single-file layout
|
|
525
|
+
}
|
|
526
|
+
if (jsonFiles.length > 0) {
|
|
527
|
+
const features = [];
|
|
528
|
+
for (const f of jsonFiles) {
|
|
529
|
+
const id = f.replace(/\.json$/, "");
|
|
530
|
+
try {
|
|
531
|
+
features.push(await readJson(this.featurePath(id), FeatureSchema));
|
|
532
|
+
}
|
|
533
|
+
catch (err) {
|
|
534
|
+
// Skip an invalid feature file rather than failing the whole load.
|
|
535
|
+
console.warn(`[plan-store] skipping invalid feature file ${f}:`, err);
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
return this.normalizeFeaturesDocument({ features }).doc;
|
|
539
|
+
}
|
|
540
|
+
// Legacy: single features.json (pre-migration read; migration writes on first write op).
|
|
541
|
+
try {
|
|
542
|
+
const legacy = await readJson(this.featuresPath(), FeaturesDocumentSchema);
|
|
543
|
+
return this.normalizeFeaturesDocument(legacy).doc;
|
|
484
544
|
}
|
|
485
545
|
catch {
|
|
486
546
|
return { features: [] };
|
|
@@ -795,13 +855,156 @@ export class PlanStore {
|
|
|
795
855
|
catch { /* best-effort */ }
|
|
796
856
|
return { removed };
|
|
797
857
|
}
|
|
858
|
+
/** All non-empty shortIds currently assigned in the project (features + phases + tasks).
|
|
859
|
+
* Read-only; used by createShortId collision guard during entity creation. */
|
|
860
|
+
async assignedShortIds() {
|
|
861
|
+
const features = await this.loadFeatures();
|
|
862
|
+
const phases = await this.loadAllPhases();
|
|
863
|
+
const ids = new Set();
|
|
864
|
+
for (const f of features.features)
|
|
865
|
+
if (f.shortId)
|
|
866
|
+
ids.add(f.shortId);
|
|
867
|
+
for (const p of phases) {
|
|
868
|
+
if (p.shortId)
|
|
869
|
+
ids.add(p.shortId);
|
|
870
|
+
for (const t of p.tasks)
|
|
871
|
+
if (t.shortId)
|
|
872
|
+
ids.add(t.shortId);
|
|
873
|
+
}
|
|
874
|
+
return ids;
|
|
875
|
+
}
|
|
876
|
+
/** Next priority (>=1) for a new entity within its scope.
|
|
877
|
+
* - feature: max priority among features + 1
|
|
878
|
+
* - phase: max priority among phases of parentId (featureId) + 1
|
|
879
|
+
* - task: max priority among tasks of parentId (phaseId) + 1 */
|
|
880
|
+
async nextPriority(kind, parentId) {
|
|
881
|
+
if (kind === "feature") {
|
|
882
|
+
const features = await this.loadFeatures();
|
|
883
|
+
const max = features.features.reduce((m, f) => Math.max(m, f.priority ?? 0), 0);
|
|
884
|
+
return max + 1;
|
|
885
|
+
}
|
|
886
|
+
if (kind === "phase") {
|
|
887
|
+
const phases = await this.loadAllPhases();
|
|
888
|
+
const siblings = phases.filter((p) => p.featureId === parentId);
|
|
889
|
+
const max = siblings.reduce((m, p) => Math.max(m, p.priority ?? 0), 0);
|
|
890
|
+
return max + 1;
|
|
891
|
+
}
|
|
892
|
+
// task
|
|
893
|
+
const phase = parentId ? await this.loadPhase(parentId).catch(() => undefined) : undefined;
|
|
894
|
+
const tasks = phase?.tasks ?? [];
|
|
895
|
+
const max = tasks.reduce((m, t) => Math.max(m, t.priority ?? 0), 0);
|
|
896
|
+
return max + 1;
|
|
897
|
+
}
|
|
898
|
+
/** Idempotent backfill of shortId (globally-unique 5-char Crockford) and priority
|
|
899
|
+
* (per-scope display order). Assigns missing shortIds and priorities; never overwrites
|
|
900
|
+
* existing non-empty shortIds or non-zero priorities. Safe to run at startup. */
|
|
901
|
+
async ensureShortIdsAndPriority() {
|
|
902
|
+
return this.runAsBatch(async () => {
|
|
903
|
+
const featuresDoc = await this.loadFeatures();
|
|
904
|
+
const phases = await this.loadAllPhases();
|
|
905
|
+
const existing = new Set();
|
|
906
|
+
for (const f of featuresDoc.features)
|
|
907
|
+
if (f.shortId)
|
|
908
|
+
existing.add(f.shortId);
|
|
909
|
+
for (const p of phases) {
|
|
910
|
+
if (p.shortId)
|
|
911
|
+
existing.add(p.shortId);
|
|
912
|
+
for (const t of p.tasks)
|
|
913
|
+
if (t.shortId)
|
|
914
|
+
existing.add(t.shortId);
|
|
915
|
+
}
|
|
916
|
+
let shortIdsAssigned = 0;
|
|
917
|
+
let prioritiesAssigned = 0;
|
|
918
|
+
let featuresDirty = false;
|
|
919
|
+
const assignPriority = (current, index) => {
|
|
920
|
+
if (current === 0) {
|
|
921
|
+
prioritiesAssigned += 1;
|
|
922
|
+
return index + 1;
|
|
923
|
+
}
|
|
924
|
+
return current;
|
|
925
|
+
};
|
|
926
|
+
// Features: shortId + priority (project scope)
|
|
927
|
+
const sortedFeatures = [...featuresDoc.features].sort((a, b) => a.number - b.number || a.createdAt.localeCompare(b.createdAt));
|
|
928
|
+
sortedFeatures.forEach((f, index) => {
|
|
929
|
+
if (!f.shortId) {
|
|
930
|
+
f.shortId = createShortId(existing);
|
|
931
|
+
existing.add(f.shortId);
|
|
932
|
+
shortIdsAssigned += 1;
|
|
933
|
+
featuresDirty = true;
|
|
934
|
+
}
|
|
935
|
+
const nextP = assignPriority(f.priority ?? 0, index);
|
|
936
|
+
if (nextP !== f.priority) {
|
|
937
|
+
f.priority = nextP;
|
|
938
|
+
featuresDirty = true;
|
|
939
|
+
}
|
|
940
|
+
});
|
|
941
|
+
if (featuresDirty) {
|
|
942
|
+
featuresDoc.features.sort((a, b) => a.priority - b.priority || a.number - b.number);
|
|
943
|
+
await this.saveFeatures(featuresDoc);
|
|
944
|
+
}
|
|
945
|
+
// Phases + tasks
|
|
946
|
+
for (const phase of phases) {
|
|
947
|
+
let phaseDirty = false;
|
|
948
|
+
if (!phase.shortId) {
|
|
949
|
+
phase.shortId = createShortId(existing);
|
|
950
|
+
existing.add(phase.shortId);
|
|
951
|
+
shortIdsAssigned += 1;
|
|
952
|
+
phaseDirty = true;
|
|
953
|
+
}
|
|
954
|
+
const phaseIndex = phase.number - 1; // stable pre-migration order
|
|
955
|
+
const nextPP = assignPriority(phase.priority ?? 0, phaseIndex < 0 ? 0 : phaseIndex);
|
|
956
|
+
if (nextPP !== phase.priority) {
|
|
957
|
+
phase.priority = nextPP;
|
|
958
|
+
phaseDirty = true;
|
|
959
|
+
}
|
|
960
|
+
const sortedTasks = [...phase.tasks].sort((a, b) => a.number - b.number || a.createdAt.localeCompare(b.createdAt));
|
|
961
|
+
sortedTasks.forEach((t, index) => {
|
|
962
|
+
if (!t.shortId) {
|
|
963
|
+
t.shortId = createShortId(existing);
|
|
964
|
+
existing.add(t.shortId);
|
|
965
|
+
shortIdsAssigned += 1;
|
|
966
|
+
phaseDirty = true;
|
|
967
|
+
}
|
|
968
|
+
const nextTP = assignPriority(t.priority ?? 0, index);
|
|
969
|
+
if (nextTP !== t.priority) {
|
|
970
|
+
t.priority = nextTP;
|
|
971
|
+
phaseDirty = true;
|
|
972
|
+
}
|
|
973
|
+
});
|
|
974
|
+
if (phaseDirty) {
|
|
975
|
+
phase.tasks.sort((a, b) => a.priority - b.priority || a.number - b.number);
|
|
976
|
+
phase.taskIds = phase.tasks.map((t) => t.id);
|
|
977
|
+
phase.updatedAt = nowISO();
|
|
978
|
+
await this.savePhase(phase);
|
|
979
|
+
}
|
|
980
|
+
}
|
|
981
|
+
// Duplicate shortId report (across all entities)
|
|
982
|
+
const allShortIds = [];
|
|
983
|
+
for (const f of featuresDoc.features)
|
|
984
|
+
if (f.shortId)
|
|
985
|
+
allShortIds.push(f.shortId);
|
|
986
|
+
for (const ph of phases) {
|
|
987
|
+
if (ph.shortId)
|
|
988
|
+
allShortIds.push(ph.shortId);
|
|
989
|
+
for (const t of ph.tasks)
|
|
990
|
+
if (t.shortId)
|
|
991
|
+
allShortIds.push(t.shortId);
|
|
992
|
+
}
|
|
993
|
+
const counts = new Map();
|
|
994
|
+
for (const id of allShortIds)
|
|
995
|
+
counts.set(id, (counts.get(id) ?? 0) + 1);
|
|
996
|
+
const duplicateShortIds = [...counts.entries()].filter(([, c]) => c > 1).map(([id]) => id);
|
|
997
|
+
return { shortIdsAssigned, prioritiesAssigned, duplicateShortIds };
|
|
998
|
+
});
|
|
999
|
+
}
|
|
798
1000
|
/** Repair dangling references and report integrity. One-shot maintenance op. */
|
|
799
1001
|
async repair() {
|
|
800
1002
|
return this.runAsBatch(async () => {
|
|
801
1003
|
const migrated = await this.migratePhaseIds();
|
|
1004
|
+
const backfill = await this.ensureShortIdsAndPriority();
|
|
802
1005
|
const integrity = await this.validateIntegrity();
|
|
803
1006
|
await this.writeGenerated();
|
|
804
|
-
return { migrated, integrity };
|
|
1007
|
+
return { migrated, backfill, integrity };
|
|
805
1008
|
});
|
|
806
1009
|
}
|
|
807
1010
|
/** Validate plan integrity: globally unique phase ids and resolvable feature.phaseIds. */
|
|
@@ -821,7 +1024,23 @@ export class PlanStore {
|
|
|
821
1024
|
danglingPhaseIds.push(`${feature.id} -> ${ref}`);
|
|
822
1025
|
}
|
|
823
1026
|
}
|
|
824
|
-
|
|
1027
|
+
// Duplicate shortIds across all entities
|
|
1028
|
+
const allShortIds = [];
|
|
1029
|
+
for (const f of features.features)
|
|
1030
|
+
if (f.shortId)
|
|
1031
|
+
allShortIds.push(f.shortId);
|
|
1032
|
+
for (const ph of phases) {
|
|
1033
|
+
if (ph.shortId)
|
|
1034
|
+
allShortIds.push(ph.shortId);
|
|
1035
|
+
for (const t of ph.tasks)
|
|
1036
|
+
if (t.shortId)
|
|
1037
|
+
allShortIds.push(t.shortId);
|
|
1038
|
+
}
|
|
1039
|
+
const sidCounts = new Map();
|
|
1040
|
+
for (const id of allShortIds)
|
|
1041
|
+
sidCounts.set(id, (sidCounts.get(id) ?? 0) + 1);
|
|
1042
|
+
const duplicateShortIds = [...sidCounts.entries()].filter(([, c]) => c > 1).map(([id]) => id);
|
|
1043
|
+
return { duplicatePhaseIds, danglingPhaseIds, duplicateShortIds };
|
|
825
1044
|
}
|
|
826
1045
|
derivePhaseStatus(phase) {
|
|
827
1046
|
if (phase.tasks.length === 0)
|
|
@@ -881,13 +1100,24 @@ export class PlanStore {
|
|
|
881
1100
|
async syncStatuses() {
|
|
882
1101
|
// Run as a batch so the internal saveFeatures + N savePhase calls do not
|
|
883
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 = [];
|
|
884
1106
|
await this.runAsBatch(async () => {
|
|
885
1107
|
await this.migratePhaseIds();
|
|
886
1108
|
const workspace = await this.loadAll();
|
|
887
1109
|
const { phases, features } = workspace;
|
|
888
|
-
|
|
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.
|
|
889
1114
|
for (const phase of phases) {
|
|
1115
|
+
const was = phase.status;
|
|
890
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
|
+
}
|
|
891
1121
|
}
|
|
892
1122
|
// 2. Update Feature statuses based on phases
|
|
893
1123
|
for (const feature of features.features) {
|
|
@@ -901,16 +1131,25 @@ export class PlanStore {
|
|
|
901
1131
|
// 4. Refresh resume focus so a subentrating agent sees current state
|
|
902
1132
|
await this.refreshResume();
|
|
903
1133
|
});
|
|
1134
|
+
return cleared;
|
|
904
1135
|
}
|
|
905
1136
|
/** Optimized rollup: syncs only the affected phase and its parent feature.
|
|
906
|
-
* Drastically reduces write operations and 'busy' window for task updates.
|
|
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. */
|
|
907
1140
|
async syncTaskStatusRollup(phaseId) {
|
|
908
1141
|
const phase = await this.loadPhase(phaseId);
|
|
1142
|
+
const was = phase.status;
|
|
909
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 = "";
|
|
910
1148
|
await this.savePhase(phase);
|
|
1149
|
+
let feature;
|
|
911
1150
|
if (phase.featureId) {
|
|
912
1151
|
const featuresDoc = await this.loadFeatures();
|
|
913
|
-
|
|
1152
|
+
feature = featuresDoc.features.find((f) => f.id === phase.featureId);
|
|
914
1153
|
if (feature) {
|
|
915
1154
|
// To derive feature status, we still need the statuses of all its phases
|
|
916
1155
|
const allPhases = await this.loadAllPhases();
|
|
@@ -919,6 +1158,7 @@ export class PlanStore {
|
|
|
919
1158
|
}
|
|
920
1159
|
}
|
|
921
1160
|
await this.refreshResume();
|
|
1161
|
+
return cleared ? formatPhaseRef(phase.number, feature?.number) : null;
|
|
922
1162
|
}
|
|
923
1163
|
// ── Savers ───────────────────────────────────────────────────────────
|
|
924
1164
|
async updateProject(updater) {
|
|
@@ -927,7 +1167,13 @@ export class PlanStore {
|
|
|
927
1167
|
return updated;
|
|
928
1168
|
}
|
|
929
1169
|
async updateFeatures(updater) {
|
|
930
|
-
const updated = await
|
|
1170
|
+
const updated = await this.withFeaturesLock(async () => {
|
|
1171
|
+
await this.migrateLegacy();
|
|
1172
|
+
const current = await this.loadFeatures();
|
|
1173
|
+
const upd = this.normalizeFeaturesDocument(updater(current)).doc;
|
|
1174
|
+
await this.saveFeaturesRaw(upd);
|
|
1175
|
+
return upd;
|
|
1176
|
+
});
|
|
931
1177
|
await this.maybeAutoSync();
|
|
932
1178
|
return updated;
|
|
933
1179
|
}
|
|
@@ -943,8 +1189,45 @@ export class PlanStore {
|
|
|
943
1189
|
await this.maybeAutoSync();
|
|
944
1190
|
}
|
|
945
1191
|
async saveFeatures(features) {
|
|
1192
|
+
await this.withFeaturesLock(async () => {
|
|
1193
|
+
await this.migrateLegacy();
|
|
1194
|
+
await this.saveFeaturesRaw(features);
|
|
1195
|
+
});
|
|
1196
|
+
await this.touchManifest();
|
|
1197
|
+
await this.maybeAutoSync();
|
|
1198
|
+
}
|
|
1199
|
+
/** Per-file write of all features + orphan reconcile. No lock (caller holds withFeaturesLock). */
|
|
1200
|
+
async saveFeaturesRaw(features) {
|
|
946
1201
|
const parsed = FeaturesDocumentSchema.parse(this.normalizeFeaturesDocument(features).doc);
|
|
947
|
-
await
|
|
1202
|
+
await mkdir(this.featuresDir(), { recursive: true });
|
|
1203
|
+
const wantIds = new Set(parsed.features.map((f) => f.id));
|
|
1204
|
+
for (const feat of parsed.features) {
|
|
1205
|
+
await atomicWriteJson(this.featurePath(feat.id), feat);
|
|
1206
|
+
}
|
|
1207
|
+
// Orphan reconcile: remove feature files no longer in the document.
|
|
1208
|
+
try {
|
|
1209
|
+
const files = await readdir(this.featuresDir());
|
|
1210
|
+
for (const f of files) {
|
|
1211
|
+
if (!f.endsWith(".json"))
|
|
1212
|
+
continue;
|
|
1213
|
+
const id = f.replace(/\.json$/, "");
|
|
1214
|
+
if (!wantIds.has(id)) {
|
|
1215
|
+
await unlink(this.featurePath(id)).catch(() => { });
|
|
1216
|
+
}
|
|
1217
|
+
}
|
|
1218
|
+
}
|
|
1219
|
+
catch {
|
|
1220
|
+
// dir absent — nothing to reconcile
|
|
1221
|
+
}
|
|
1222
|
+
}
|
|
1223
|
+
/** Granular single-feature write (per-file lock; parallel-safe across features). */
|
|
1224
|
+
async saveFeature(feature) {
|
|
1225
|
+
await this.withFeaturesLock(async () => {
|
|
1226
|
+
await this.migrateLegacy();
|
|
1227
|
+
await mkdir(this.featuresDir(), { recursive: true });
|
|
1228
|
+
const parsed = FeatureSchema.parse(feature);
|
|
1229
|
+
await atomicWriteJson(this.featurePath(parsed.id), parsed);
|
|
1230
|
+
});
|
|
948
1231
|
await this.touchManifest();
|
|
949
1232
|
await this.maybeAutoSync();
|
|
950
1233
|
}
|
|
@@ -968,6 +1251,45 @@ export class PlanStore {
|
|
|
968
1251
|
await this.maybeAutoSync();
|
|
969
1252
|
return updated;
|
|
970
1253
|
}
|
|
1254
|
+
// ── Phase-scoped handoff (entity field, harness-agnostic) ────────────
|
|
1255
|
+
/** Get the handoff text for a phase ("" if none). Throws if phase missing. */
|
|
1256
|
+
async getPhaseHandoff(phaseId) {
|
|
1257
|
+
return (await this.loadPhase(phaseId)).handoff;
|
|
1258
|
+
}
|
|
1259
|
+
/** Set the handoff text for a phase + stamp handoffUpdatedAt. Atomic per-file
|
|
1260
|
+
* update via updatePhase (so the web UI refreshes via maybeAutoSync). */
|
|
1261
|
+
async setPhaseHandoff(phaseId, text) {
|
|
1262
|
+
const now = new Date().toISOString();
|
|
1263
|
+
await this.updatePhase(phaseId, (phase) => ({ ...phase, handoff: text, handoffUpdatedAt: now }));
|
|
1264
|
+
}
|
|
1265
|
+
/** Clear the handoff text for a phase (handoff=""). handoffUpdatedAt is left
|
|
1266
|
+
* unchanged as an audit trail (when a handoff last existed). */
|
|
1267
|
+
async clearPhaseHandoff(phaseId) {
|
|
1268
|
+
await this.updatePhase(phaseId, (phase) => ({ ...phase, handoff: "" }));
|
|
1269
|
+
}
|
|
1270
|
+
/** List all phases that have a non-empty handoff, newest first, with a
|
|
1271
|
+
* human-readable composite ref (P00x or P00x(F00x)) and a first-line excerpt. */
|
|
1272
|
+
async listHandoffs() {
|
|
1273
|
+
const phases = await this.loadAllPhases();
|
|
1274
|
+
const features = await this.loadFeatures();
|
|
1275
|
+
const featureNumber = new Map();
|
|
1276
|
+
for (const f of features.features)
|
|
1277
|
+
featureNumber.set(f.id, f.number);
|
|
1278
|
+
const out = [];
|
|
1279
|
+
for (const p of phases) {
|
|
1280
|
+
if (!p.handoff)
|
|
1281
|
+
continue;
|
|
1282
|
+
const fnum = p.featureId ? featureNumber.get(p.featureId) : undefined;
|
|
1283
|
+
out.push({
|
|
1284
|
+
phaseId: p.id,
|
|
1285
|
+
compositeRef: formatPhaseRef(p.number, fnum),
|
|
1286
|
+
updatedAt: p.handoffUpdatedAt || p.updatedAt,
|
|
1287
|
+
firstLine: handoffFirstLine(p.handoff),
|
|
1288
|
+
});
|
|
1289
|
+
}
|
|
1290
|
+
out.sort((a, b) => b.updatedAt.localeCompare(a.updatedAt));
|
|
1291
|
+
return out;
|
|
1292
|
+
}
|
|
971
1293
|
async deletePhase(phaseId) {
|
|
972
1294
|
try {
|
|
973
1295
|
await unlink(this.phasePath(phaseId));
|
package/dist/refs.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Harness-agnostic reference resolution for planner entities.
|
|
3
|
+
*
|
|
4
|
+
* Used by adapters (pi-adapter, plan-mcp) and any future harness to resolve a
|
|
5
|
+
* human-facing ref to a concrete entity. Kept in @agent-plan/core so every
|
|
6
|
+
* adapter shares the exact same resolution semantics.
|
|
7
|
+
*
|
|
8
|
+
* Supported phase refs (case-insensitive):
|
|
9
|
+
* - UUID: "bd6ed366-..." -> phase.id
|
|
10
|
+
* - Short: "P001" | "p1" -> phase.number (globally unique)
|
|
11
|
+
* - Compos: "P002(F001)" -> phase.number with parent feature validation
|
|
12
|
+
* - Title: exact match, then includes (backward-compat fallback)
|
|
13
|
+
*/
|
|
14
|
+
import type { Phase, Feature } from "./schema.js";
|
|
15
|
+
/**
|
|
16
|
+
* Resolve a phase reference to a Phase. Returns `undefined` when not found or
|
|
17
|
+
* when a composite (F00x) parent does not match the phase's featureId.
|
|
18
|
+
*
|
|
19
|
+
* @param phases all phases (st.loadAllPhases())
|
|
20
|
+
* @param features all features (st.loadAllFeatures() / loadFeatures())
|
|
21
|
+
* @param ref the human-facing ref (P00x / P00x(F00x) / UUID / title)
|
|
22
|
+
*/
|
|
23
|
+
export declare function findPhaseByRef(phases: Phase[], features: Feature[], ref: string): Phase | undefined;
|
|
24
|
+
//# sourceMappingURL=refs.d.ts.map
|
|
@@ -0,0 +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"}
|
package/dist/refs.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// P00x or P00x(F00x) — accept 1+ digits so "p1" == "p001".
|
|
2
|
+
const PHASE_REF_RE = /^p(\d+)(?:\(f(\d+)\))?$/;
|
|
3
|
+
/**
|
|
4
|
+
* Resolve a phase reference to a Phase. Returns `undefined` when not found or
|
|
5
|
+
* when a composite (F00x) parent does not match the phase's featureId.
|
|
6
|
+
*
|
|
7
|
+
* @param phases all phases (st.loadAllPhases())
|
|
8
|
+
* @param features all features (st.loadAllFeatures() / loadFeatures())
|
|
9
|
+
* @param ref the human-facing ref (P00x / P00x(F00x) / UUID / title)
|
|
10
|
+
*/
|
|
11
|
+
export function findPhaseByRef(phases, features, ref) {
|
|
12
|
+
const normalized = ref.trim().toLowerCase();
|
|
13
|
+
if (!normalized)
|
|
14
|
+
return undefined;
|
|
15
|
+
// 1. UUID (exact)
|
|
16
|
+
let found = phases.find((p) => p.id.toLowerCase() === normalized);
|
|
17
|
+
if (found)
|
|
18
|
+
return found;
|
|
19
|
+
// 2. Composite / short ref: P00x or P00x(F00x)
|
|
20
|
+
const m = normalized.match(PHASE_REF_RE);
|
|
21
|
+
if (m) {
|
|
22
|
+
const phaseNum = parseInt(m[1], 10);
|
|
23
|
+
found = phases.find((p) => p.number === phaseNum);
|
|
24
|
+
if (found && m[2]) {
|
|
25
|
+
// validate parent feature when the (F00x) disambiguator is present
|
|
26
|
+
const featureNum = parseInt(m[2], 10);
|
|
27
|
+
const feat = features.find((f) => f.number === featureNum);
|
|
28
|
+
if (!feat || found.featureId !== feat.id)
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
31
|
+
if (found)
|
|
32
|
+
return found;
|
|
33
|
+
}
|
|
34
|
+
// 3. Title fallback (backward compatibility with agents using titles)
|
|
35
|
+
return (phases.find((p) => p.title.toLowerCase() === normalized) ??
|
|
36
|
+
phases.find((p) => p.title.toLowerCase().includes(normalized)));
|
|
37
|
+
}
|
package/dist/schema.d.ts
CHANGED
|
@@ -442,6 +442,8 @@ export declare const TaskSchema: z.ZodEffects<z.ZodObject<{
|
|
|
442
442
|
id: z.ZodString;
|
|
443
443
|
phaseId: z.ZodString;
|
|
444
444
|
number: z.ZodDefault<z.ZodNumber>;
|
|
445
|
+
shortId: z.ZodDefault<z.ZodString>;
|
|
446
|
+
priority: z.ZodDefault<z.ZodNumber>;
|
|
445
447
|
shortName: z.ZodString;
|
|
446
448
|
title: z.ZodString;
|
|
447
449
|
status: z.ZodEnum<["planned", "in-progress", "done", "blocked", "canceled", "rejected", "deferred", "waiting"]>;
|
|
@@ -551,6 +553,8 @@ export declare const TaskSchema: z.ZodEffects<z.ZodObject<{
|
|
|
551
553
|
acceptedAt: string;
|
|
552
554
|
}[];
|
|
553
555
|
phaseId: string;
|
|
556
|
+
shortId: string;
|
|
557
|
+
priority: number;
|
|
554
558
|
shortName: string;
|
|
555
559
|
statusLog: {
|
|
556
560
|
id: string;
|
|
@@ -596,6 +600,8 @@ export declare const TaskSchema: z.ZodEffects<z.ZodObject<{
|
|
|
596
600
|
rationale?: string | undefined;
|
|
597
601
|
implementationNotes?: string | undefined;
|
|
598
602
|
}[] | undefined;
|
|
603
|
+
shortId?: string | undefined;
|
|
604
|
+
priority?: number | undefined;
|
|
599
605
|
statusLog?: {
|
|
600
606
|
id: string;
|
|
601
607
|
date: string;
|
|
@@ -644,6 +650,8 @@ export declare const TaskSchema: z.ZodEffects<z.ZodObject<{
|
|
|
644
650
|
acceptedAt: string;
|
|
645
651
|
}[];
|
|
646
652
|
phaseId: string;
|
|
653
|
+
shortId: string;
|
|
654
|
+
priority: number;
|
|
647
655
|
shortName: string;
|
|
648
656
|
statusLog: {
|
|
649
657
|
id: string;
|
|
@@ -684,6 +692,8 @@ export declare const TaskSchema: z.ZodEffects<z.ZodObject<{
|
|
|
684
692
|
rationale?: string | undefined;
|
|
685
693
|
implementationNotes?: string | undefined;
|
|
686
694
|
}[] | undefined;
|
|
695
|
+
shortId?: string | undefined;
|
|
696
|
+
priority?: number | undefined;
|
|
687
697
|
statusLog?: {
|
|
688
698
|
id: string;
|
|
689
699
|
date: string;
|
|
@@ -713,6 +723,8 @@ export declare const PhaseSchema: z.ZodObject<{
|
|
|
713
723
|
id: z.ZodString;
|
|
714
724
|
featureId: z.ZodOptional<z.ZodString>;
|
|
715
725
|
number: z.ZodNumber;
|
|
726
|
+
shortId: z.ZodDefault<z.ZodString>;
|
|
727
|
+
priority: z.ZodDefault<z.ZodNumber>;
|
|
716
728
|
slug: z.ZodString;
|
|
717
729
|
title: z.ZodString;
|
|
718
730
|
status: z.ZodEnum<["draft", "discovery", "planned", "in-progress", "done", "blocked", "canceled", "rejected", "deferred", "waiting"]>;
|
|
@@ -757,6 +769,8 @@ export declare const PhaseSchema: z.ZodObject<{
|
|
|
757
769
|
id: z.ZodString;
|
|
758
770
|
phaseId: z.ZodString;
|
|
759
771
|
number: z.ZodDefault<z.ZodNumber>;
|
|
772
|
+
shortId: z.ZodDefault<z.ZodString>;
|
|
773
|
+
priority: z.ZodDefault<z.ZodNumber>;
|
|
760
774
|
shortName: z.ZodString;
|
|
761
775
|
title: z.ZodString;
|
|
762
776
|
status: z.ZodEnum<["planned", "in-progress", "done", "blocked", "canceled", "rejected", "deferred", "waiting"]>;
|
|
@@ -866,6 +880,8 @@ export declare const PhaseSchema: z.ZodObject<{
|
|
|
866
880
|
acceptedAt: string;
|
|
867
881
|
}[];
|
|
868
882
|
phaseId: string;
|
|
883
|
+
shortId: string;
|
|
884
|
+
priority: number;
|
|
869
885
|
shortName: string;
|
|
870
886
|
statusLog: {
|
|
871
887
|
id: string;
|
|
@@ -911,6 +927,8 @@ export declare const PhaseSchema: z.ZodObject<{
|
|
|
911
927
|
rationale?: string | undefined;
|
|
912
928
|
implementationNotes?: string | undefined;
|
|
913
929
|
}[] | undefined;
|
|
930
|
+
shortId?: string | undefined;
|
|
931
|
+
priority?: number | undefined;
|
|
914
932
|
statusLog?: {
|
|
915
933
|
id: string;
|
|
916
934
|
date: string;
|
|
@@ -959,6 +977,8 @@ export declare const PhaseSchema: z.ZodObject<{
|
|
|
959
977
|
acceptedAt: string;
|
|
960
978
|
}[];
|
|
961
979
|
phaseId: string;
|
|
980
|
+
shortId: string;
|
|
981
|
+
priority: number;
|
|
962
982
|
shortName: string;
|
|
963
983
|
statusLog: {
|
|
964
984
|
id: string;
|
|
@@ -999,6 +1019,8 @@ export declare const PhaseSchema: z.ZodObject<{
|
|
|
999
1019
|
rationale?: string | undefined;
|
|
1000
1020
|
implementationNotes?: string | undefined;
|
|
1001
1021
|
}[] | undefined;
|
|
1022
|
+
shortId?: string | undefined;
|
|
1023
|
+
priority?: number | undefined;
|
|
1002
1024
|
statusLog?: {
|
|
1003
1025
|
id: string;
|
|
1004
1026
|
date: string;
|
|
@@ -1026,6 +1048,8 @@ export declare const PhaseSchema: z.ZodObject<{
|
|
|
1026
1048
|
}>, "many">>;
|
|
1027
1049
|
createdAt: z.ZodString;
|
|
1028
1050
|
updatedAt: z.ZodString;
|
|
1051
|
+
handoff: z.ZodDefault<z.ZodString>;
|
|
1052
|
+
handoffUpdatedAt: z.ZodDefault<z.ZodString>;
|
|
1029
1053
|
}, "strip", z.ZodTypeAny, {
|
|
1030
1054
|
number: number;
|
|
1031
1055
|
status: "planned" | "in-progress" | "done" | "blocked" | "canceled" | "rejected" | "deferred" | "waiting" | "draft" | "discovery";
|
|
@@ -1046,6 +1070,8 @@ export declare const PhaseSchema: z.ZodObject<{
|
|
|
1046
1070
|
implementationNotes: string;
|
|
1047
1071
|
acceptedAt: string;
|
|
1048
1072
|
}[];
|
|
1073
|
+
shortId: string;
|
|
1074
|
+
priority: number;
|
|
1049
1075
|
dependsOn: string[];
|
|
1050
1076
|
slug: string;
|
|
1051
1077
|
discussedAt: string;
|
|
@@ -1081,6 +1107,8 @@ export declare const PhaseSchema: z.ZodObject<{
|
|
|
1081
1107
|
acceptedAt: string;
|
|
1082
1108
|
}[];
|
|
1083
1109
|
phaseId: string;
|
|
1110
|
+
shortId: string;
|
|
1111
|
+
priority: number;
|
|
1084
1112
|
shortName: string;
|
|
1085
1113
|
statusLog: {
|
|
1086
1114
|
id: string;
|
|
@@ -1102,6 +1130,8 @@ export declare const PhaseSchema: z.ZodObject<{
|
|
|
1102
1130
|
startedAt: string;
|
|
1103
1131
|
completedAt: string;
|
|
1104
1132
|
}[];
|
|
1133
|
+
handoff: string;
|
|
1134
|
+
handoffUpdatedAt: string;
|
|
1105
1135
|
featureId?: string | undefined;
|
|
1106
1136
|
}, {
|
|
1107
1137
|
number: number;
|
|
@@ -1124,6 +1154,8 @@ export declare const PhaseSchema: z.ZodObject<{
|
|
|
1124
1154
|
rationale?: string | undefined;
|
|
1125
1155
|
implementationNotes?: string | undefined;
|
|
1126
1156
|
}[] | undefined;
|
|
1157
|
+
shortId?: string | undefined;
|
|
1158
|
+
priority?: number | undefined;
|
|
1127
1159
|
dependsOn?: string[] | undefined;
|
|
1128
1160
|
featureId?: string | undefined;
|
|
1129
1161
|
discussedAt?: string | undefined;
|
|
@@ -1155,6 +1187,8 @@ export declare const PhaseSchema: z.ZodObject<{
|
|
|
1155
1187
|
rationale?: string | undefined;
|
|
1156
1188
|
implementationNotes?: string | undefined;
|
|
1157
1189
|
}[] | undefined;
|
|
1190
|
+
shortId?: string | undefined;
|
|
1191
|
+
priority?: number | undefined;
|
|
1158
1192
|
statusLog?: {
|
|
1159
1193
|
id: string;
|
|
1160
1194
|
date: string;
|
|
@@ -1180,10 +1214,14 @@ export declare const PhaseSchema: z.ZodObject<{
|
|
|
1180
1214
|
startedAt?: string | undefined;
|
|
1181
1215
|
completedAt?: string | undefined;
|
|
1182
1216
|
}[] | undefined;
|
|
1217
|
+
handoff?: string | undefined;
|
|
1218
|
+
handoffUpdatedAt?: string | undefined;
|
|
1183
1219
|
}>;
|
|
1184
1220
|
export declare const FeatureSchema: z.ZodObject<{
|
|
1185
1221
|
id: z.ZodString;
|
|
1186
1222
|
number: z.ZodDefault<z.ZodNumber>;
|
|
1223
|
+
shortId: z.ZodDefault<z.ZodString>;
|
|
1224
|
+
priority: z.ZodDefault<z.ZodNumber>;
|
|
1187
1225
|
name: z.ZodString;
|
|
1188
1226
|
description: z.ZodDefault<z.ZodString>;
|
|
1189
1227
|
status: z.ZodEnum<["planned", "in-progress", "done", "blocked", "canceled", "rejected", "deferred", "waiting"]>;
|
|
@@ -1236,6 +1274,8 @@ export declare const FeatureSchema: z.ZodObject<{
|
|
|
1236
1274
|
implementationNotes: string;
|
|
1237
1275
|
acceptedAt: string;
|
|
1238
1276
|
}[];
|
|
1277
|
+
shortId: string;
|
|
1278
|
+
priority: number;
|
|
1239
1279
|
dependsOn: string[];
|
|
1240
1280
|
discussedAt: string;
|
|
1241
1281
|
contextReady: boolean;
|
|
@@ -1261,6 +1301,8 @@ export declare const FeatureSchema: z.ZodObject<{
|
|
|
1261
1301
|
rationale?: string | undefined;
|
|
1262
1302
|
implementationNotes?: string | undefined;
|
|
1263
1303
|
}[] | undefined;
|
|
1304
|
+
shortId?: string | undefined;
|
|
1305
|
+
priority?: number | undefined;
|
|
1264
1306
|
dependsOn?: string[] | undefined;
|
|
1265
1307
|
discussedAt?: string | undefined;
|
|
1266
1308
|
contextReady?: boolean | undefined;
|
|
@@ -1275,6 +1317,8 @@ export declare const FeaturesDocumentSchema: z.ZodObject<{
|
|
|
1275
1317
|
features: z.ZodArray<z.ZodObject<{
|
|
1276
1318
|
id: z.ZodString;
|
|
1277
1319
|
number: z.ZodDefault<z.ZodNumber>;
|
|
1320
|
+
shortId: z.ZodDefault<z.ZodString>;
|
|
1321
|
+
priority: z.ZodDefault<z.ZodNumber>;
|
|
1278
1322
|
name: z.ZodString;
|
|
1279
1323
|
description: z.ZodDefault<z.ZodString>;
|
|
1280
1324
|
status: z.ZodEnum<["planned", "in-progress", "done", "blocked", "canceled", "rejected", "deferred", "waiting"]>;
|
|
@@ -1327,6 +1371,8 @@ export declare const FeaturesDocumentSchema: z.ZodObject<{
|
|
|
1327
1371
|
implementationNotes: string;
|
|
1328
1372
|
acceptedAt: string;
|
|
1329
1373
|
}[];
|
|
1374
|
+
shortId: string;
|
|
1375
|
+
priority: number;
|
|
1330
1376
|
dependsOn: string[];
|
|
1331
1377
|
discussedAt: string;
|
|
1332
1378
|
contextReady: boolean;
|
|
@@ -1352,6 +1398,8 @@ export declare const FeaturesDocumentSchema: z.ZodObject<{
|
|
|
1352
1398
|
rationale?: string | undefined;
|
|
1353
1399
|
implementationNotes?: string | undefined;
|
|
1354
1400
|
}[] | undefined;
|
|
1401
|
+
shortId?: string | undefined;
|
|
1402
|
+
priority?: number | undefined;
|
|
1355
1403
|
dependsOn?: string[] | undefined;
|
|
1356
1404
|
discussedAt?: string | undefined;
|
|
1357
1405
|
contextReady?: boolean | undefined;
|
|
@@ -1379,6 +1427,8 @@ export declare const FeaturesDocumentSchema: z.ZodObject<{
|
|
|
1379
1427
|
implementationNotes: string;
|
|
1380
1428
|
acceptedAt: string;
|
|
1381
1429
|
}[];
|
|
1430
|
+
shortId: string;
|
|
1431
|
+
priority: number;
|
|
1382
1432
|
dependsOn: string[];
|
|
1383
1433
|
discussedAt: string;
|
|
1384
1434
|
contextReady: boolean;
|
|
@@ -1406,6 +1456,8 @@ export declare const FeaturesDocumentSchema: z.ZodObject<{
|
|
|
1406
1456
|
rationale?: string | undefined;
|
|
1407
1457
|
implementationNotes?: string | undefined;
|
|
1408
1458
|
}[] | undefined;
|
|
1459
|
+
shortId?: string | undefined;
|
|
1460
|
+
priority?: number | undefined;
|
|
1409
1461
|
dependsOn?: string[] | undefined;
|
|
1410
1462
|
discussedAt?: string | undefined;
|
|
1411
1463
|
contextReady?: boolean | undefined;
|
|
@@ -1728,6 +1780,8 @@ export declare const PlanWorkspaceSchema: z.ZodObject<{
|
|
|
1728
1780
|
features: z.ZodArray<z.ZodObject<{
|
|
1729
1781
|
id: z.ZodString;
|
|
1730
1782
|
number: z.ZodDefault<z.ZodNumber>;
|
|
1783
|
+
shortId: z.ZodDefault<z.ZodString>;
|
|
1784
|
+
priority: z.ZodDefault<z.ZodNumber>;
|
|
1731
1785
|
name: z.ZodString;
|
|
1732
1786
|
description: z.ZodDefault<z.ZodString>;
|
|
1733
1787
|
status: z.ZodEnum<["planned", "in-progress", "done", "blocked", "canceled", "rejected", "deferred", "waiting"]>;
|
|
@@ -1780,6 +1834,8 @@ export declare const PlanWorkspaceSchema: z.ZodObject<{
|
|
|
1780
1834
|
implementationNotes: string;
|
|
1781
1835
|
acceptedAt: string;
|
|
1782
1836
|
}[];
|
|
1837
|
+
shortId: string;
|
|
1838
|
+
priority: number;
|
|
1783
1839
|
dependsOn: string[];
|
|
1784
1840
|
discussedAt: string;
|
|
1785
1841
|
contextReady: boolean;
|
|
@@ -1805,6 +1861,8 @@ export declare const PlanWorkspaceSchema: z.ZodObject<{
|
|
|
1805
1861
|
rationale?: string | undefined;
|
|
1806
1862
|
implementationNotes?: string | undefined;
|
|
1807
1863
|
}[] | undefined;
|
|
1864
|
+
shortId?: string | undefined;
|
|
1865
|
+
priority?: number | undefined;
|
|
1808
1866
|
dependsOn?: string[] | undefined;
|
|
1809
1867
|
discussedAt?: string | undefined;
|
|
1810
1868
|
contextReady?: boolean | undefined;
|
|
@@ -1832,6 +1890,8 @@ export declare const PlanWorkspaceSchema: z.ZodObject<{
|
|
|
1832
1890
|
implementationNotes: string;
|
|
1833
1891
|
acceptedAt: string;
|
|
1834
1892
|
}[];
|
|
1893
|
+
shortId: string;
|
|
1894
|
+
priority: number;
|
|
1835
1895
|
dependsOn: string[];
|
|
1836
1896
|
discussedAt: string;
|
|
1837
1897
|
contextReady: boolean;
|
|
@@ -1859,6 +1919,8 @@ export declare const PlanWorkspaceSchema: z.ZodObject<{
|
|
|
1859
1919
|
rationale?: string | undefined;
|
|
1860
1920
|
implementationNotes?: string | undefined;
|
|
1861
1921
|
}[] | undefined;
|
|
1922
|
+
shortId?: string | undefined;
|
|
1923
|
+
priority?: number | undefined;
|
|
1862
1924
|
dependsOn?: string[] | undefined;
|
|
1863
1925
|
discussedAt?: string | undefined;
|
|
1864
1926
|
contextReady?: boolean | undefined;
|
|
@@ -1975,6 +2037,8 @@ export declare const PlanWorkspaceSchema: z.ZodObject<{
|
|
|
1975
2037
|
id: z.ZodString;
|
|
1976
2038
|
featureId: z.ZodOptional<z.ZodString>;
|
|
1977
2039
|
number: z.ZodNumber;
|
|
2040
|
+
shortId: z.ZodDefault<z.ZodString>;
|
|
2041
|
+
priority: z.ZodDefault<z.ZodNumber>;
|
|
1978
2042
|
slug: z.ZodString;
|
|
1979
2043
|
title: z.ZodString;
|
|
1980
2044
|
status: z.ZodEnum<["draft", "discovery", "planned", "in-progress", "done", "blocked", "canceled", "rejected", "deferred", "waiting"]>;
|
|
@@ -2019,6 +2083,8 @@ export declare const PlanWorkspaceSchema: z.ZodObject<{
|
|
|
2019
2083
|
id: z.ZodString;
|
|
2020
2084
|
phaseId: z.ZodString;
|
|
2021
2085
|
number: z.ZodDefault<z.ZodNumber>;
|
|
2086
|
+
shortId: z.ZodDefault<z.ZodString>;
|
|
2087
|
+
priority: z.ZodDefault<z.ZodNumber>;
|
|
2022
2088
|
shortName: z.ZodString;
|
|
2023
2089
|
title: z.ZodString;
|
|
2024
2090
|
status: z.ZodEnum<["planned", "in-progress", "done", "blocked", "canceled", "rejected", "deferred", "waiting"]>;
|
|
@@ -2128,6 +2194,8 @@ export declare const PlanWorkspaceSchema: z.ZodObject<{
|
|
|
2128
2194
|
acceptedAt: string;
|
|
2129
2195
|
}[];
|
|
2130
2196
|
phaseId: string;
|
|
2197
|
+
shortId: string;
|
|
2198
|
+
priority: number;
|
|
2131
2199
|
shortName: string;
|
|
2132
2200
|
statusLog: {
|
|
2133
2201
|
id: string;
|
|
@@ -2173,6 +2241,8 @@ export declare const PlanWorkspaceSchema: z.ZodObject<{
|
|
|
2173
2241
|
rationale?: string | undefined;
|
|
2174
2242
|
implementationNotes?: string | undefined;
|
|
2175
2243
|
}[] | undefined;
|
|
2244
|
+
shortId?: string | undefined;
|
|
2245
|
+
priority?: number | undefined;
|
|
2176
2246
|
statusLog?: {
|
|
2177
2247
|
id: string;
|
|
2178
2248
|
date: string;
|
|
@@ -2221,6 +2291,8 @@ export declare const PlanWorkspaceSchema: z.ZodObject<{
|
|
|
2221
2291
|
acceptedAt: string;
|
|
2222
2292
|
}[];
|
|
2223
2293
|
phaseId: string;
|
|
2294
|
+
shortId: string;
|
|
2295
|
+
priority: number;
|
|
2224
2296
|
shortName: string;
|
|
2225
2297
|
statusLog: {
|
|
2226
2298
|
id: string;
|
|
@@ -2261,6 +2333,8 @@ export declare const PlanWorkspaceSchema: z.ZodObject<{
|
|
|
2261
2333
|
rationale?: string | undefined;
|
|
2262
2334
|
implementationNotes?: string | undefined;
|
|
2263
2335
|
}[] | undefined;
|
|
2336
|
+
shortId?: string | undefined;
|
|
2337
|
+
priority?: number | undefined;
|
|
2264
2338
|
statusLog?: {
|
|
2265
2339
|
id: string;
|
|
2266
2340
|
date: string;
|
|
@@ -2288,6 +2362,8 @@ export declare const PlanWorkspaceSchema: z.ZodObject<{
|
|
|
2288
2362
|
}>, "many">>;
|
|
2289
2363
|
createdAt: z.ZodString;
|
|
2290
2364
|
updatedAt: z.ZodString;
|
|
2365
|
+
handoff: z.ZodDefault<z.ZodString>;
|
|
2366
|
+
handoffUpdatedAt: z.ZodDefault<z.ZodString>;
|
|
2291
2367
|
}, "strip", z.ZodTypeAny, {
|
|
2292
2368
|
number: number;
|
|
2293
2369
|
status: "planned" | "in-progress" | "done" | "blocked" | "canceled" | "rejected" | "deferred" | "waiting" | "draft" | "discovery";
|
|
@@ -2308,6 +2384,8 @@ export declare const PlanWorkspaceSchema: z.ZodObject<{
|
|
|
2308
2384
|
implementationNotes: string;
|
|
2309
2385
|
acceptedAt: string;
|
|
2310
2386
|
}[];
|
|
2387
|
+
shortId: string;
|
|
2388
|
+
priority: number;
|
|
2311
2389
|
dependsOn: string[];
|
|
2312
2390
|
slug: string;
|
|
2313
2391
|
discussedAt: string;
|
|
@@ -2343,6 +2421,8 @@ export declare const PlanWorkspaceSchema: z.ZodObject<{
|
|
|
2343
2421
|
acceptedAt: string;
|
|
2344
2422
|
}[];
|
|
2345
2423
|
phaseId: string;
|
|
2424
|
+
shortId: string;
|
|
2425
|
+
priority: number;
|
|
2346
2426
|
shortName: string;
|
|
2347
2427
|
statusLog: {
|
|
2348
2428
|
id: string;
|
|
@@ -2364,6 +2444,8 @@ export declare const PlanWorkspaceSchema: z.ZodObject<{
|
|
|
2364
2444
|
startedAt: string;
|
|
2365
2445
|
completedAt: string;
|
|
2366
2446
|
}[];
|
|
2447
|
+
handoff: string;
|
|
2448
|
+
handoffUpdatedAt: string;
|
|
2367
2449
|
featureId?: string | undefined;
|
|
2368
2450
|
}, {
|
|
2369
2451
|
number: number;
|
|
@@ -2386,6 +2468,8 @@ export declare const PlanWorkspaceSchema: z.ZodObject<{
|
|
|
2386
2468
|
rationale?: string | undefined;
|
|
2387
2469
|
implementationNotes?: string | undefined;
|
|
2388
2470
|
}[] | undefined;
|
|
2471
|
+
shortId?: string | undefined;
|
|
2472
|
+
priority?: number | undefined;
|
|
2389
2473
|
dependsOn?: string[] | undefined;
|
|
2390
2474
|
featureId?: string | undefined;
|
|
2391
2475
|
discussedAt?: string | undefined;
|
|
@@ -2417,6 +2501,8 @@ export declare const PlanWorkspaceSchema: z.ZodObject<{
|
|
|
2417
2501
|
rationale?: string | undefined;
|
|
2418
2502
|
implementationNotes?: string | undefined;
|
|
2419
2503
|
}[] | undefined;
|
|
2504
|
+
shortId?: string | undefined;
|
|
2505
|
+
priority?: number | undefined;
|
|
2420
2506
|
statusLog?: {
|
|
2421
2507
|
id: string;
|
|
2422
2508
|
date: string;
|
|
@@ -2442,6 +2528,8 @@ export declare const PlanWorkspaceSchema: z.ZodObject<{
|
|
|
2442
2528
|
startedAt?: string | undefined;
|
|
2443
2529
|
completedAt?: string | undefined;
|
|
2444
2530
|
}[] | undefined;
|
|
2531
|
+
handoff?: string | undefined;
|
|
2532
|
+
handoffUpdatedAt?: string | undefined;
|
|
2445
2533
|
}>, "many">;
|
|
2446
2534
|
}, "strip", z.ZodTypeAny, {
|
|
2447
2535
|
features: {
|
|
@@ -2461,6 +2549,8 @@ export declare const PlanWorkspaceSchema: z.ZodObject<{
|
|
|
2461
2549
|
implementationNotes: string;
|
|
2462
2550
|
acceptedAt: string;
|
|
2463
2551
|
}[];
|
|
2552
|
+
shortId: string;
|
|
2553
|
+
priority: number;
|
|
2464
2554
|
dependsOn: string[];
|
|
2465
2555
|
discussedAt: string;
|
|
2466
2556
|
contextReady: boolean;
|
|
@@ -2545,6 +2635,8 @@ export declare const PlanWorkspaceSchema: z.ZodObject<{
|
|
|
2545
2635
|
implementationNotes: string;
|
|
2546
2636
|
acceptedAt: string;
|
|
2547
2637
|
}[];
|
|
2638
|
+
shortId: string;
|
|
2639
|
+
priority: number;
|
|
2548
2640
|
dependsOn: string[];
|
|
2549
2641
|
slug: string;
|
|
2550
2642
|
discussedAt: string;
|
|
@@ -2580,6 +2672,8 @@ export declare const PlanWorkspaceSchema: z.ZodObject<{
|
|
|
2580
2672
|
acceptedAt: string;
|
|
2581
2673
|
}[];
|
|
2582
2674
|
phaseId: string;
|
|
2675
|
+
shortId: string;
|
|
2676
|
+
priority: number;
|
|
2583
2677
|
shortName: string;
|
|
2584
2678
|
statusLog: {
|
|
2585
2679
|
id: string;
|
|
@@ -2601,6 +2695,8 @@ export declare const PlanWorkspaceSchema: z.ZodObject<{
|
|
|
2601
2695
|
startedAt: string;
|
|
2602
2696
|
completedAt: string;
|
|
2603
2697
|
}[];
|
|
2698
|
+
handoff: string;
|
|
2699
|
+
handoffUpdatedAt: string;
|
|
2604
2700
|
featureId?: string | undefined;
|
|
2605
2701
|
}[];
|
|
2606
2702
|
}, {
|
|
@@ -2621,6 +2717,8 @@ export declare const PlanWorkspaceSchema: z.ZodObject<{
|
|
|
2621
2717
|
rationale?: string | undefined;
|
|
2622
2718
|
implementationNotes?: string | undefined;
|
|
2623
2719
|
}[] | undefined;
|
|
2720
|
+
shortId?: string | undefined;
|
|
2721
|
+
priority?: number | undefined;
|
|
2624
2722
|
dependsOn?: string[] | undefined;
|
|
2625
2723
|
discussedAt?: string | undefined;
|
|
2626
2724
|
contextReady?: boolean | undefined;
|
|
@@ -2706,6 +2804,8 @@ export declare const PlanWorkspaceSchema: z.ZodObject<{
|
|
|
2706
2804
|
rationale?: string | undefined;
|
|
2707
2805
|
implementationNotes?: string | undefined;
|
|
2708
2806
|
}[] | undefined;
|
|
2807
|
+
shortId?: string | undefined;
|
|
2808
|
+
priority?: number | undefined;
|
|
2709
2809
|
dependsOn?: string[] | undefined;
|
|
2710
2810
|
featureId?: string | undefined;
|
|
2711
2811
|
discussedAt?: string | undefined;
|
|
@@ -2737,6 +2837,8 @@ export declare const PlanWorkspaceSchema: z.ZodObject<{
|
|
|
2737
2837
|
rationale?: string | undefined;
|
|
2738
2838
|
implementationNotes?: string | undefined;
|
|
2739
2839
|
}[] | undefined;
|
|
2840
|
+
shortId?: string | undefined;
|
|
2841
|
+
priority?: number | undefined;
|
|
2740
2842
|
statusLog?: {
|
|
2741
2843
|
id: string;
|
|
2742
2844
|
date: string;
|
|
@@ -2762,6 +2864,8 @@ export declare const PlanWorkspaceSchema: z.ZodObject<{
|
|
|
2762
2864
|
startedAt?: string | undefined;
|
|
2763
2865
|
completedAt?: string | undefined;
|
|
2764
2866
|
}[] | undefined;
|
|
2867
|
+
handoff?: string | undefined;
|
|
2868
|
+
handoffUpdatedAt?: string | undefined;
|
|
2765
2869
|
}[];
|
|
2766
2870
|
}>;
|
|
2767
2871
|
export type Timestamp = z.infer<typeof TimestampSchema>;
|
package/dist/schema.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,eAAe,aAAwB,CAAC;AACrD,eAAO,MAAM,UAAU,aAAiD,CAAC;AAEzE,eAAO,MAAM,kBAAkB;;;;;;;;;EAG7B,CAAC;AAEH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;EAK7B,CAAC;AAEH,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAmBhC,CAAC;AAEH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;EAS5B,CAAC;AAEH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;EAM9B,CAAC;AAEH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAE5B,CAAC;AAEH,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;EAMzB,CAAC;AAEH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;EAI9B,CAAC;AAEH,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;EAOjC,CAAC;AAEH,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAexB,CAAC;AAEH,eAAO,MAAM,mBAAmB,yGAAuG,CAAC;AACxI,eAAO,MAAM,gBAAgB,yGAAuG,CAAC;AACrI,eAAO,MAAM,iBAAiB,+HAA6H,CAAC;AAC5J,eAAO,MAAM,uBAAuB,yGAAuG,CAAC;AAC5I,eAAO,MAAM,mBAAmB,yGAAuG,CAAC;AAExI,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;EAOxB,CAAC;AAEH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;EAI9B,CAAC;AAIH,wEAAwE;AACxE,eAAO,MAAM,8BAA8B,aAEzC,CAAC;AAEH;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAK7E;AAED,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;EAO/B,CAAC;AAEH,eAAO,MAAM,UAAU
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"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"}
|
package/dist/schema.js
CHANGED
|
@@ -138,6 +138,8 @@ export const TaskSchema = z.object({
|
|
|
138
138
|
id: z.string(),
|
|
139
139
|
phaseId: z.string(),
|
|
140
140
|
number: z.number().int().nonnegative().default(0),
|
|
141
|
+
shortId: z.string().regex(/^(|[A-Z2-9]{5})$/).default(""),
|
|
142
|
+
priority: z.number().int().nonnegative().default(0),
|
|
141
143
|
shortName: SlugSchema,
|
|
142
144
|
title: z.string().min(1),
|
|
143
145
|
status: TaskStatusSchema,
|
|
@@ -165,6 +167,8 @@ export const PhaseSchema = z.object({
|
|
|
165
167
|
id: z.string(),
|
|
166
168
|
featureId: z.string().optional(),
|
|
167
169
|
number: z.number().int().positive(),
|
|
170
|
+
shortId: z.string().regex(/^(|[A-Z2-9]{5})$/).default(""),
|
|
171
|
+
priority: z.number().int().nonnegative().default(0),
|
|
168
172
|
slug: SlugSchema,
|
|
169
173
|
title: z.string().min(1),
|
|
170
174
|
status: PhaseStatusSchema,
|
|
@@ -187,10 +191,14 @@ export const PhaseSchema = z.object({
|
|
|
187
191
|
tasks: z.array(TaskSchema).default([]),
|
|
188
192
|
createdAt: TimestampSchema,
|
|
189
193
|
updatedAt: TimestampSchema,
|
|
194
|
+
handoff: z.string().default(""),
|
|
195
|
+
handoffUpdatedAt: z.string().default(""),
|
|
190
196
|
});
|
|
191
197
|
export const FeatureSchema = z.object({
|
|
192
198
|
id: z.string(),
|
|
193
199
|
number: z.number().int().nonnegative().default(0),
|
|
200
|
+
shortId: z.string().regex(/^(|[A-Z2-9]{5})$/).default(""),
|
|
201
|
+
priority: z.number().int().nonnegative().default(0),
|
|
194
202
|
name: z.string().min(1),
|
|
195
203
|
description: z.string().default(""),
|
|
196
204
|
status: FeatureStatusSchema,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-plan/core",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.19-next.0",
|
|
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",
|
|
@@ -42,6 +42,7 @@
|
|
|
42
42
|
},
|
|
43
43
|
"scripts": {
|
|
44
44
|
"build": "tsc -p tsconfig.json",
|
|
45
|
-
"check": "tsc -p tsconfig.json --noEmit"
|
|
45
|
+
"check": "tsc -p tsconfig.json --noEmit",
|
|
46
|
+
"test": "tsc -p tsconfig.json && node --test \"test/**/*.test.mjs\""
|
|
46
47
|
}
|
|
47
48
|
}
|