@s_s/harmonia 1.2.0 → 1.3.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/build/core/dispatch.d.ts +14 -11
- package/build/core/dispatch.js +37 -32
- package/build/core/dispatch.js.map +1 -1
- package/build/core/docs.d.ts +15 -11
- package/build/core/docs.js +23 -18
- package/build/core/docs.js.map +1 -1
- package/build/core/issues.d.ts +37 -0
- package/build/core/issues.js +100 -0
- package/build/core/issues.js.map +1 -0
- package/build/core/registry.d.ts +34 -0
- package/build/core/registry.js +59 -0
- package/build/core/registry.js.map +1 -1
- package/build/core/reviews.d.ts +9 -8
- package/build/core/reviews.js +21 -19
- package/build/core/reviews.js.map +1 -1
- package/build/core/state.d.ts +22 -14
- package/build/core/state.js +52 -30
- package/build/core/state.js.map +1 -1
- package/build/core/steps.d.ts +8 -7
- package/build/core/steps.js +20 -18
- package/build/core/steps.js.map +1 -1
- package/build/core/types.d.ts +31 -2
- package/build/index.js +4 -0
- package/build/index.js.map +1 -1
- package/build/setup/templates.js +70 -1
- package/build/setup/templates.js.map +1 -1
- package/build/tools/approve-doc.js +9 -31
- package/build/tools/approve-doc.js.map +1 -1
- package/build/tools/dispatch-role.js +8 -19
- package/build/tools/dispatch-role.js.map +1 -1
- package/build/tools/doc-tools.js +98 -62
- package/build/tools/doc-tools.js.map +1 -1
- package/build/tools/get-project-status.js +69 -24
- package/build/tools/get-project-status.js.map +1 -1
- package/build/tools/issue-tools.d.ts +10 -0
- package/build/tools/issue-tools.js +169 -0
- package/build/tools/issue-tools.js.map +1 -0
- package/build/tools/iteration-start.js +9 -4
- package/build/tools/iteration-start.js.map +1 -1
- package/build/tools/patch-start.d.ts +14 -0
- package/build/tools/patch-start.js +97 -0
- package/build/tools/patch-start.js.map +1 -0
- package/build/tools/project-init.js +6 -8
- package/build/tools/project-init.js.map +1 -1
- package/build/tools/report-dispatch.js +21 -32
- package/build/tools/report-dispatch.js.map +1 -1
- package/build/tools/set-scale.js +7 -19
- package/build/tools/set-scale.js.map +1 -1
- package/build/tools/update-phase.js +11 -22
- package/build/tools/update-phase.js.map +1 -1
- package/build/tools/utils.d.ts +34 -0
- package/build/tools/utils.js +61 -0
- package/build/tools/utils.js.map +1 -0
- package/package.json +1 -1
package/build/core/registry.js
CHANGED
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
* ├── overrides.json # global overrides (optional)
|
|
14
14
|
* ├── my-app/
|
|
15
15
|
* │ ├── overrides.json # project-level overrides (optional)
|
|
16
|
+
* │ ├── issues.json # project-level issue tracking (optional)
|
|
16
17
|
* │ ├── iter-1/
|
|
17
18
|
* │ │ ├── state.json
|
|
18
19
|
* │ │ ├── docs/
|
|
@@ -20,6 +21,10 @@
|
|
|
20
21
|
* │ │ └── ...
|
|
21
22
|
* │ ├── iter-2/
|
|
22
23
|
* │ │ └── ...
|
|
24
|
+
* │ ├── patch-1/
|
|
25
|
+
* │ │ ├── state.json # type: "patch", clarify/design skipped
|
|
26
|
+
* │ │ ├── docs/
|
|
27
|
+
* │ │ └── ...
|
|
23
28
|
* └── another-project/
|
|
24
29
|
* └── ...
|
|
25
30
|
*/
|
|
@@ -84,6 +89,9 @@ export async function registerProject(projectName, projectDir, workflow) {
|
|
|
84
89
|
createdAt: new Date().toISOString(),
|
|
85
90
|
currentIteration: 0,
|
|
86
91
|
totalIterations: 0,
|
|
92
|
+
currentPatch: 0,
|
|
93
|
+
totalPatches: 0,
|
|
94
|
+
activeContext: '',
|
|
87
95
|
};
|
|
88
96
|
// Create project data directory under global dir
|
|
89
97
|
const dataDir = getProjectDataDir(projectName);
|
|
@@ -143,10 +151,61 @@ export async function startIteration(projectName) {
|
|
|
143
151
|
const newIteration = entry.totalIterations + 1;
|
|
144
152
|
entry.currentIteration = newIteration;
|
|
145
153
|
entry.totalIterations = newIteration;
|
|
154
|
+
entry.activeContext = `iter-${newIteration}`;
|
|
146
155
|
// Create iteration directory with docs subdirectory
|
|
147
156
|
const iterDir = getIterationDir(projectName, newIteration);
|
|
148
157
|
await mkdir(join(iterDir, 'docs'), { recursive: true });
|
|
149
158
|
await writeRegistry(registry);
|
|
150
159
|
return newIteration;
|
|
151
160
|
}
|
|
161
|
+
/**
|
|
162
|
+
* Get the patch directory for a specific project patch.
|
|
163
|
+
* Pure path concatenation — does NOT check if the directory exists.
|
|
164
|
+
*/
|
|
165
|
+
export function getPatchDir(projectName, patch) {
|
|
166
|
+
return join(getProjectDataDir(projectName), `patch-${patch}`);
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Start a new patch for a project.
|
|
170
|
+
* Creates the patch directory (with docs/ subdirectory) and updates the registry.
|
|
171
|
+
*
|
|
172
|
+
* @returns The new patch number
|
|
173
|
+
*/
|
|
174
|
+
export async function startPatch(projectName) {
|
|
175
|
+
const registry = await readRegistry();
|
|
176
|
+
const entry = registry.projects[projectName];
|
|
177
|
+
if (!entry) {
|
|
178
|
+
throw new Error(`Project "${projectName}" not found in registry.`);
|
|
179
|
+
}
|
|
180
|
+
const newPatch = entry.totalPatches + 1;
|
|
181
|
+
entry.currentPatch = newPatch;
|
|
182
|
+
entry.totalPatches = newPatch;
|
|
183
|
+
entry.activeContext = `patch-${newPatch}`;
|
|
184
|
+
// Create patch directory with docs subdirectory
|
|
185
|
+
const patchDir = getPatchDir(projectName, newPatch);
|
|
186
|
+
await mkdir(join(patchDir, 'docs'), { recursive: true });
|
|
187
|
+
await writeRegistry(registry);
|
|
188
|
+
return newPatch;
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Resolve the active context directory for a project.
|
|
192
|
+
* Parses activeContext string (e.g. "iter-1", "patch-2") into an absolute path.
|
|
193
|
+
*
|
|
194
|
+
* @returns { dir: string, type: 'iteration' | 'patch', number: number } or null if no active context
|
|
195
|
+
*/
|
|
196
|
+
export function resolveContextDir(projectName, activeContext) {
|
|
197
|
+
if (!activeContext)
|
|
198
|
+
return null;
|
|
199
|
+
const iterMatch = activeContext.match(/^iter-(\d+)$/);
|
|
200
|
+
if (iterMatch) {
|
|
201
|
+
const num = parseInt(iterMatch[1], 10);
|
|
202
|
+
return { dir: getIterationDir(projectName, num), type: 'iteration', number: num };
|
|
203
|
+
}
|
|
204
|
+
const patchMatch = activeContext.match(/^patch-(\d+)$/);
|
|
205
|
+
if (patchMatch) {
|
|
206
|
+
const num = parseInt(patchMatch[1], 10);
|
|
207
|
+
return { dir: getPatchDir(projectName, num), type: 'patch', number: num };
|
|
208
|
+
}
|
|
209
|
+
return null;
|
|
210
|
+
}
|
|
152
211
|
//# sourceMappingURL=registry.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/core/registry.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/core/registry.ts"],"names":[],"mappings":"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"}
|
package/build/core/reviews.d.ts
CHANGED
|
@@ -1,26 +1,27 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Document review state management — <
|
|
2
|
+
* Document review state management — <context_dir>/reviews.json
|
|
3
3
|
*
|
|
4
4
|
* Tracks which documents are pending review, approved, or rejected.
|
|
5
|
+
* All public functions accept an optional contextDir parameter.
|
|
5
6
|
*/
|
|
6
7
|
import type { DocReviewState } from './types.js';
|
|
7
8
|
/**
|
|
8
|
-
* Read the reviews state for a project
|
|
9
|
+
* Read the reviews state for a project context.
|
|
9
10
|
*/
|
|
10
|
-
export declare function readReviews(projectName: string, iteration: number): Promise<Record<string, DocReviewState>>;
|
|
11
|
+
export declare function readReviews(projectName: string, iteration: number, contextDir?: string): Promise<Record<string, DocReviewState>>;
|
|
11
12
|
/**
|
|
12
13
|
* Submit a document for review. Sets status to "pending".
|
|
13
14
|
*/
|
|
14
|
-
export declare function submitForReview(projectName: string, iteration: number, docId: string): Promise<DocReviewState>;
|
|
15
|
+
export declare function submitForReview(projectName: string, iteration: number, docId: string, contextDir?: string): Promise<DocReviewState>;
|
|
15
16
|
/**
|
|
16
17
|
* Approve or reject a document review.
|
|
17
18
|
*/
|
|
18
|
-
export declare function resolveReview(projectName: string, iteration: number, docId: string, status: 'approved' | 'rejected', comment?: string): Promise<DocReviewState>;
|
|
19
|
+
export declare function resolveReview(projectName: string, iteration: number, docId: string, status: 'approved' | 'rejected', comment?: string, contextDir?: string): Promise<DocReviewState>;
|
|
19
20
|
/**
|
|
20
21
|
* Get the review state for a specific document.
|
|
21
22
|
*/
|
|
22
|
-
export declare function getDocReview(projectName: string, iteration: number, docId: string): Promise<DocReviewState | null>;
|
|
23
|
+
export declare function getDocReview(projectName: string, iteration: number, docId: string, contextDir?: string): Promise<DocReviewState | null>;
|
|
23
24
|
/**
|
|
24
|
-
* Get all pending reviews for a project
|
|
25
|
+
* Get all pending reviews for a project context.
|
|
25
26
|
*/
|
|
26
|
-
export declare function getPendingReviews(projectName: string, iteration: number): Promise<DocReviewState[]>;
|
|
27
|
+
export declare function getPendingReviews(projectName: string, iteration: number, contextDir?: string): Promise<DocReviewState[]>;
|
package/build/core/reviews.js
CHANGED
|
@@ -1,21 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Document review state management — <
|
|
2
|
+
* Document review state management — <context_dir>/reviews.json
|
|
3
3
|
*
|
|
4
4
|
* Tracks which documents are pending review, approved, or rejected.
|
|
5
|
+
* All public functions accept an optional contextDir parameter.
|
|
5
6
|
*/
|
|
6
7
|
import { readFile, writeFile, mkdir } from 'node:fs/promises';
|
|
7
8
|
import { join, dirname } from 'node:path';
|
|
8
9
|
import { getIterationDir } from './registry.js';
|
|
9
10
|
const REVIEWS_FILE = 'reviews.json';
|
|
10
|
-
function reviewsPath(projectName, iteration) {
|
|
11
|
-
|
|
11
|
+
function reviewsPath(projectName, iteration, contextDir) {
|
|
12
|
+
const base = contextDir ?? getIterationDir(projectName, iteration);
|
|
13
|
+
return join(base, REVIEWS_FILE);
|
|
12
14
|
}
|
|
13
15
|
/**
|
|
14
|
-
* Read the reviews state for a project
|
|
16
|
+
* Read the reviews state for a project context.
|
|
15
17
|
*/
|
|
16
|
-
export async function readReviews(projectName, iteration) {
|
|
18
|
+
export async function readReviews(projectName, iteration, contextDir) {
|
|
17
19
|
try {
|
|
18
|
-
const content = await readFile(reviewsPath(projectName, iteration), 'utf-8');
|
|
20
|
+
const content = await readFile(reviewsPath(projectName, iteration, contextDir), 'utf-8');
|
|
19
21
|
const data = JSON.parse(content);
|
|
20
22
|
return data.docs ?? {};
|
|
21
23
|
}
|
|
@@ -26,8 +28,8 @@ export async function readReviews(projectName, iteration) {
|
|
|
26
28
|
/**
|
|
27
29
|
* Write reviews state to disk.
|
|
28
30
|
*/
|
|
29
|
-
async function writeReviews(projectName, iteration, docs) {
|
|
30
|
-
const filePath = reviewsPath(projectName, iteration);
|
|
31
|
+
async function writeReviews(projectName, iteration, docs, contextDir) {
|
|
32
|
+
const filePath = reviewsPath(projectName, iteration, contextDir);
|
|
31
33
|
await mkdir(dirname(filePath), { recursive: true });
|
|
32
34
|
const data = { docs };
|
|
33
35
|
await writeFile(filePath, JSON.stringify(data, null, 2) + '\n', 'utf-8');
|
|
@@ -35,22 +37,22 @@ async function writeReviews(projectName, iteration, docs) {
|
|
|
35
37
|
/**
|
|
36
38
|
* Submit a document for review. Sets status to "pending".
|
|
37
39
|
*/
|
|
38
|
-
export async function submitForReview(projectName, iteration, docId) {
|
|
39
|
-
const reviews = await readReviews(projectName, iteration);
|
|
40
|
+
export async function submitForReview(projectName, iteration, docId, contextDir) {
|
|
41
|
+
const reviews = await readReviews(projectName, iteration, contextDir);
|
|
40
42
|
const state = {
|
|
41
43
|
docId,
|
|
42
44
|
status: 'pending',
|
|
43
45
|
submittedAt: new Date().toISOString(),
|
|
44
46
|
};
|
|
45
47
|
reviews[docId] = state;
|
|
46
|
-
await writeReviews(projectName, iteration, reviews);
|
|
48
|
+
await writeReviews(projectName, iteration, reviews, contextDir);
|
|
47
49
|
return state;
|
|
48
50
|
}
|
|
49
51
|
/**
|
|
50
52
|
* Approve or reject a document review.
|
|
51
53
|
*/
|
|
52
|
-
export async function resolveReview(projectName, iteration, docId, status, comment) {
|
|
53
|
-
const reviews = await readReviews(projectName, iteration);
|
|
54
|
+
export async function resolveReview(projectName, iteration, docId, status, comment, contextDir) {
|
|
55
|
+
const reviews = await readReviews(projectName, iteration, contextDir);
|
|
54
56
|
const existing = reviews[docId];
|
|
55
57
|
if (!existing) {
|
|
56
58
|
throw new Error(`No review pending for document "${docId}". Submit it for review first.`);
|
|
@@ -63,21 +65,21 @@ export async function resolveReview(projectName, iteration, docId, status, comme
|
|
|
63
65
|
if (comment) {
|
|
64
66
|
existing.comment = comment;
|
|
65
67
|
}
|
|
66
|
-
await writeReviews(projectName, iteration, reviews);
|
|
68
|
+
await writeReviews(projectName, iteration, reviews, contextDir);
|
|
67
69
|
return existing;
|
|
68
70
|
}
|
|
69
71
|
/**
|
|
70
72
|
* Get the review state for a specific document.
|
|
71
73
|
*/
|
|
72
|
-
export async function getDocReview(projectName, iteration, docId) {
|
|
73
|
-
const reviews = await readReviews(projectName, iteration);
|
|
74
|
+
export async function getDocReview(projectName, iteration, docId, contextDir) {
|
|
75
|
+
const reviews = await readReviews(projectName, iteration, contextDir);
|
|
74
76
|
return reviews[docId] ?? null;
|
|
75
77
|
}
|
|
76
78
|
/**
|
|
77
|
-
* Get all pending reviews for a project
|
|
79
|
+
* Get all pending reviews for a project context.
|
|
78
80
|
*/
|
|
79
|
-
export async function getPendingReviews(projectName, iteration) {
|
|
80
|
-
const reviews = await readReviews(projectName, iteration);
|
|
81
|
+
export async function getPendingReviews(projectName, iteration, contextDir) {
|
|
82
|
+
const reviews = await readReviews(projectName, iteration, contextDir);
|
|
81
83
|
return Object.values(reviews).filter((r) => r.status === 'pending');
|
|
82
84
|
}
|
|
83
85
|
//# sourceMappingURL=reviews.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reviews.js","sourceRoot":"","sources":["../../src/core/reviews.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"reviews.js","sourceRoot":"","sources":["../../src/core/reviews.ts"],"names":[],"mappings":"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"}
|
package/build/core/state.d.ts
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Project state management — manages
|
|
2
|
+
* Project state management — manages state.json within iteration/patch directories.
|
|
3
|
+
*
|
|
4
|
+
* All functions accept an optional `contextDir` parameter. When provided, it is used
|
|
5
|
+
* directly as the directory containing state.json. When omitted, the directory is
|
|
6
|
+
* resolved from `getIterationDir(projectName, iteration)` for backward compatibility.
|
|
3
7
|
*/
|
|
4
|
-
import type { PhaseStatus, ProjectScale, ProjectState, LoadedWorkflow } from './types.js';
|
|
8
|
+
import type { ContextType, PhaseStatus, ProjectScale, ProjectState, LoadedWorkflow } from './types.js';
|
|
5
9
|
/**
|
|
6
10
|
* Error thrown when a tool requires scale but it hasn't been set yet.
|
|
7
11
|
*/
|
|
@@ -9,28 +13,32 @@ export declare class ScaleNotSetError extends Error {
|
|
|
9
13
|
constructor(projectName: string);
|
|
10
14
|
}
|
|
11
15
|
/**
|
|
12
|
-
* Initialize a new project state file
|
|
13
|
-
*
|
|
14
|
-
*
|
|
16
|
+
* Initialize a new project state file.
|
|
17
|
+
*
|
|
18
|
+
* For iteration mode (default): all phases start normally (first = in_progress, rest = pending).
|
|
19
|
+
* For patch mode: clarify/design are marked as "skipped", first non-skipped phase is in_progress,
|
|
20
|
+
* scale is set to "small" automatically.
|
|
21
|
+
*
|
|
22
|
+
* @param contextDir - Optional explicit directory. If omitted, uses getIterationDir().
|
|
15
23
|
*/
|
|
16
|
-
export declare function initProjectState(projectName: string, projectDir: string, workflow: LoadedWorkflow, iteration: number): Promise<ProjectState>;
|
|
24
|
+
export declare function initProjectState(projectName: string, projectDir: string, workflow: LoadedWorkflow, iteration: number, type?: ContextType, contextDir?: string): Promise<ProjectState>;
|
|
17
25
|
/**
|
|
18
|
-
* Read the current project state
|
|
26
|
+
* Read the current project state.
|
|
19
27
|
*/
|
|
20
|
-
export declare function readState(projectName: string, iteration: number): Promise<ProjectState>;
|
|
28
|
+
export declare function readState(projectName: string, iteration: number, contextDir?: string): Promise<ProjectState>;
|
|
21
29
|
/**
|
|
22
|
-
* Write project state to disk
|
|
30
|
+
* Write project state to disk.
|
|
23
31
|
*/
|
|
24
|
-
export declare function writeState(projectName: string, iteration: number, state: ProjectState): Promise<void>;
|
|
32
|
+
export declare function writeState(projectName: string, iteration: number, state: ProjectState, contextDir?: string): Promise<void>;
|
|
25
33
|
/**
|
|
26
34
|
* Update a specific phase's status.
|
|
27
35
|
*/
|
|
28
|
-
export declare function updatePhaseStatus(projectName: string, iteration: number, phaseId: string, status: PhaseStatus, blockedReason?: string): Promise<ProjectState>;
|
|
36
|
+
export declare function updatePhaseStatus(projectName: string, iteration: number, phaseId: string, status: PhaseStatus, blockedReason?: string, contextDir?: string): Promise<ProjectState>;
|
|
29
37
|
/**
|
|
30
|
-
* Check if a project state file exists
|
|
38
|
+
* Check if a project state file exists.
|
|
31
39
|
*/
|
|
32
|
-
export declare function projectStateExists(projectName: string, iteration: number): Promise<boolean>;
|
|
40
|
+
export declare function projectStateExists(projectName: string, iteration: number, contextDir?: string): Promise<boolean>;
|
|
33
41
|
/**
|
|
34
42
|
* Set the project scale. Scale is immutable once set.
|
|
35
43
|
*/
|
|
36
|
-
export declare function setScale(projectName: string, iteration: number, scale: ProjectScale): Promise<ProjectState>;
|
|
44
|
+
export declare function setScale(projectName: string, iteration: number, scale: ProjectScale, contextDir?: string): Promise<ProjectState>;
|
package/build/core/state.js
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Project state management — manages
|
|
2
|
+
* Project state management — manages state.json within iteration/patch directories.
|
|
3
|
+
*
|
|
4
|
+
* All functions accept an optional `contextDir` parameter. When provided, it is used
|
|
5
|
+
* directly as the directory containing state.json. When omitted, the directory is
|
|
6
|
+
* resolved from `getIterationDir(projectName, iteration)` for backward compatibility.
|
|
3
7
|
*/
|
|
4
8
|
import { mkdir, readFile, writeFile } from 'node:fs/promises';
|
|
5
9
|
import { join, dirname } from 'node:path';
|
|
@@ -14,48 +18,65 @@ export class ScaleNotSetError extends Error {
|
|
|
14
18
|
}
|
|
15
19
|
}
|
|
16
20
|
const STATE_FILE = 'state.json';
|
|
17
|
-
function
|
|
18
|
-
return
|
|
21
|
+
function resolveDir(projectName, iteration, contextDir) {
|
|
22
|
+
return contextDir ?? getIterationDir(projectName, iteration);
|
|
19
23
|
}
|
|
24
|
+
function statePath(projectName, iteration, contextDir) {
|
|
25
|
+
return join(resolveDir(projectName, iteration, contextDir), STATE_FILE);
|
|
26
|
+
}
|
|
27
|
+
/** Phases to skip in patch mode (clarify and design) */
|
|
28
|
+
const PATCH_SKIP_PHASES = new Set(['clarify', 'design']);
|
|
20
29
|
/**
|
|
21
|
-
* Initialize a new project state file
|
|
22
|
-
*
|
|
23
|
-
*
|
|
30
|
+
* Initialize a new project state file.
|
|
31
|
+
*
|
|
32
|
+
* For iteration mode (default): all phases start normally (first = in_progress, rest = pending).
|
|
33
|
+
* For patch mode: clarify/design are marked as "skipped", first non-skipped phase is in_progress,
|
|
34
|
+
* scale is set to "small" automatically.
|
|
35
|
+
*
|
|
36
|
+
* @param contextDir - Optional explicit directory. If omitted, uses getIterationDir().
|
|
24
37
|
*/
|
|
25
|
-
export async function initProjectState(projectName, projectDir, workflow, iteration) {
|
|
38
|
+
export async function initProjectState(projectName, projectDir, workflow, iteration, type = 'iteration', contextDir) {
|
|
26
39
|
const now = new Date().toISOString();
|
|
27
40
|
const phases = workflow.definition.phases;
|
|
28
|
-
const
|
|
41
|
+
const isPatch = type === 'patch';
|
|
42
|
+
// Find the first non-skipped phase
|
|
43
|
+
const firstActiveIndex = isPatch ? phases.findIndex((p) => !PATCH_SKIP_PHASES.has(p.id)) : 0;
|
|
44
|
+
const firstPhaseId = phases[firstActiveIndex]?.id ?? phases[0]?.id ?? '';
|
|
29
45
|
const state = {
|
|
30
46
|
projectName,
|
|
31
47
|
projectDir,
|
|
32
48
|
workflow: workflow.definition.name,
|
|
49
|
+
type,
|
|
33
50
|
iteration,
|
|
34
|
-
scale: null,
|
|
51
|
+
scale: isPatch ? 'small' : null,
|
|
35
52
|
currentPhase: firstPhaseId,
|
|
36
|
-
phases: phases.map((p, i) =>
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
53
|
+
phases: phases.map((p, i) => {
|
|
54
|
+
if (isPatch && PATCH_SKIP_PHASES.has(p.id)) {
|
|
55
|
+
return { id: p.id, status: 'skipped' };
|
|
56
|
+
}
|
|
57
|
+
if (i === firstActiveIndex) {
|
|
58
|
+
return { id: p.id, status: 'in_progress', startedAt: now };
|
|
59
|
+
}
|
|
60
|
+
return { id: p.id, status: 'pending' };
|
|
61
|
+
}),
|
|
41
62
|
createdAt: now,
|
|
42
63
|
updatedAt: now,
|
|
43
64
|
};
|
|
44
|
-
await writeState(projectName, iteration, state);
|
|
65
|
+
await writeState(projectName, iteration, state, contextDir);
|
|
45
66
|
return state;
|
|
46
67
|
}
|
|
47
68
|
/**
|
|
48
|
-
* Read the current project state
|
|
69
|
+
* Read the current project state.
|
|
49
70
|
*/
|
|
50
|
-
export async function readState(projectName, iteration) {
|
|
51
|
-
const content = await readFile(statePath(projectName, iteration), 'utf-8');
|
|
71
|
+
export async function readState(projectName, iteration, contextDir) {
|
|
72
|
+
const content = await readFile(statePath(projectName, iteration, contextDir), 'utf-8');
|
|
52
73
|
return JSON.parse(content);
|
|
53
74
|
}
|
|
54
75
|
/**
|
|
55
|
-
* Write project state to disk
|
|
76
|
+
* Write project state to disk.
|
|
56
77
|
*/
|
|
57
|
-
export async function writeState(projectName, iteration, state) {
|
|
58
|
-
const filePath = statePath(projectName, iteration);
|
|
78
|
+
export async function writeState(projectName, iteration, state, contextDir) {
|
|
79
|
+
const filePath = statePath(projectName, iteration, contextDir);
|
|
59
80
|
await mkdir(dirname(filePath), { recursive: true });
|
|
60
81
|
state.updatedAt = new Date().toISOString();
|
|
61
82
|
await writeFile(filePath, JSON.stringify(state, null, 2) + '\n', 'utf-8');
|
|
@@ -63,8 +84,8 @@ export async function writeState(projectName, iteration, state) {
|
|
|
63
84
|
/**
|
|
64
85
|
* Update a specific phase's status.
|
|
65
86
|
*/
|
|
66
|
-
export async function updatePhaseStatus(projectName, iteration, phaseId, status, blockedReason) {
|
|
67
|
-
const state = await readState(projectName, iteration);
|
|
87
|
+
export async function updatePhaseStatus(projectName, iteration, phaseId, status, blockedReason, contextDir) {
|
|
88
|
+
const state = await readState(projectName, iteration, contextDir);
|
|
68
89
|
const phase = state.phases.find((p) => p.id === phaseId);
|
|
69
90
|
if (!phase) {
|
|
70
91
|
throw new Error(`Phase "${phaseId}" not found in project state`);
|
|
@@ -86,6 +107,7 @@ export async function updatePhaseStatus(projectName, iteration, phaseId, status,
|
|
|
86
107
|
state.currentPhase = phaseId;
|
|
87
108
|
}
|
|
88
109
|
// If completing a phase, auto-advance currentPhase to the next pending one
|
|
110
|
+
// (skip over phases that are already "skipped")
|
|
89
111
|
if (status === 'completed') {
|
|
90
112
|
const idx = state.phases.findIndex((p) => p.id === phaseId);
|
|
91
113
|
const next = state.phases.find((p, i) => i > idx && p.status === 'pending');
|
|
@@ -95,15 +117,15 @@ export async function updatePhaseStatus(projectName, iteration, phaseId, status,
|
|
|
95
117
|
state.currentPhase = next.id;
|
|
96
118
|
}
|
|
97
119
|
}
|
|
98
|
-
await writeState(projectName, iteration, state);
|
|
120
|
+
await writeState(projectName, iteration, state, contextDir);
|
|
99
121
|
return state;
|
|
100
122
|
}
|
|
101
123
|
/**
|
|
102
|
-
* Check if a project state file exists
|
|
124
|
+
* Check if a project state file exists.
|
|
103
125
|
*/
|
|
104
|
-
export async function projectStateExists(projectName, iteration) {
|
|
126
|
+
export async function projectStateExists(projectName, iteration, contextDir) {
|
|
105
127
|
try {
|
|
106
|
-
await readFile(statePath(projectName, iteration), 'utf-8');
|
|
128
|
+
await readFile(statePath(projectName, iteration, contextDir), 'utf-8');
|
|
107
129
|
return true;
|
|
108
130
|
}
|
|
109
131
|
catch {
|
|
@@ -113,13 +135,13 @@ export async function projectStateExists(projectName, iteration) {
|
|
|
113
135
|
/**
|
|
114
136
|
* Set the project scale. Scale is immutable once set.
|
|
115
137
|
*/
|
|
116
|
-
export async function setScale(projectName, iteration, scale) {
|
|
117
|
-
const state = await readState(projectName, iteration);
|
|
138
|
+
export async function setScale(projectName, iteration, scale, contextDir) {
|
|
139
|
+
const state = await readState(projectName, iteration, contextDir);
|
|
118
140
|
if (state.scale !== null) {
|
|
119
141
|
throw new Error(`Scale 已设定为 "${state.scale}",不可更改。如需调整规模,请重新评估 PRD。`);
|
|
120
142
|
}
|
|
121
143
|
state.scale = scale;
|
|
122
|
-
await writeState(projectName, iteration, state);
|
|
144
|
+
await writeState(projectName, iteration, state, contextDir);
|
|
123
145
|
return state;
|
|
124
146
|
}
|
|
125
147
|
//# sourceMappingURL=state.js.map
|
package/build/core/state.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"state.js","sourceRoot":"","sources":["../../src/core/state.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"state.js","sourceRoot":"","sources":["../../src/core/state.ts"],"names":[],"mappings":"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"}
|
package/build/core/steps.d.ts
CHANGED
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Step state management — manages <
|
|
2
|
+
* Step state management — manages <context_dir>/steps.json
|
|
3
3
|
*
|
|
4
4
|
* Tracks which sequential steps have been completed for each document,
|
|
5
5
|
* supporting the P3 Sequential mode feature.
|
|
6
|
+
* All public functions accept an optional contextDir parameter.
|
|
6
7
|
*/
|
|
7
8
|
import type { DocStepState } from './types.js';
|
|
8
9
|
/**
|
|
9
|
-
* Read the steps state for a project
|
|
10
|
+
* Read the steps state for a project context.
|
|
10
11
|
*/
|
|
11
|
-
export declare function readSteps(projectName: string, iteration: number): Promise<Record<string, DocStepState>>;
|
|
12
|
+
export declare function readSteps(projectName: string, iteration: number, contextDir?: string): Promise<Record<string, DocStepState>>;
|
|
12
13
|
/**
|
|
13
14
|
* Get the step state for a specific document.
|
|
14
15
|
*/
|
|
15
|
-
export declare function getDocStepState(projectName: string, iteration: number, docId: string): Promise<DocStepState | null>;
|
|
16
|
+
export declare function getDocStepState(projectName: string, iteration: number, docId: string, contextDir?: string): Promise<DocStepState | null>;
|
|
16
17
|
/**
|
|
17
18
|
* Get the set of completed step IDs for a document.
|
|
18
19
|
*/
|
|
@@ -23,12 +24,12 @@ export declare function getCompletedStepIds(state: DocStepState | null): Set<str
|
|
|
23
24
|
*
|
|
24
25
|
* @returns The updated DocStepState
|
|
25
26
|
*/
|
|
26
|
-
export declare function recordStepCompletion(projectName: string, iteration: number, docId: string, stepId: string, artifactPath: string, allStepIds: string[]): Promise<DocStepState>;
|
|
27
|
+
export declare function recordStepCompletion(projectName: string, iteration: number, docId: string, stepId: string, artifactPath: string, allStepIds: string[], contextDir?: string): Promise<DocStepState>;
|
|
27
28
|
/**
|
|
28
29
|
* Mark a document as finalized (all steps completed + final doc written).
|
|
29
30
|
*/
|
|
30
|
-
export declare function markFinalized(projectName: string, iteration: number, docId: string): Promise<DocStepState>;
|
|
31
|
+
export declare function markFinalized(projectName: string, iteration: number, docId: string, contextDir?: string): Promise<DocStepState>;
|
|
31
32
|
/**
|
|
32
33
|
* Check if a document's sequential process is finalized.
|
|
33
34
|
*/
|
|
34
|
-
export declare function isDocFinalized(projectName: string, iteration: number, docId: string): Promise<boolean>;
|
|
35
|
+
export declare function isDocFinalized(projectName: string, iteration: number, docId: string, contextDir?: string): Promise<boolean>;
|
package/build/core/steps.js
CHANGED
|
@@ -1,22 +1,24 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Step state management — manages <
|
|
2
|
+
* Step state management — manages <context_dir>/steps.json
|
|
3
3
|
*
|
|
4
4
|
* Tracks which sequential steps have been completed for each document,
|
|
5
5
|
* supporting the P3 Sequential mode feature.
|
|
6
|
+
* All public functions accept an optional contextDir parameter.
|
|
6
7
|
*/
|
|
7
8
|
import { readFile, writeFile, mkdir } from 'node:fs/promises';
|
|
8
9
|
import { join, dirname } from 'node:path';
|
|
9
10
|
import { getIterationDir } from './registry.js';
|
|
10
11
|
const STEPS_FILE = 'steps.json';
|
|
11
|
-
function stepsPath(projectName, iteration) {
|
|
12
|
-
|
|
12
|
+
function stepsPath(projectName, iteration, contextDir) {
|
|
13
|
+
const base = contextDir ?? getIterationDir(projectName, iteration);
|
|
14
|
+
return join(base, STEPS_FILE);
|
|
13
15
|
}
|
|
14
16
|
/**
|
|
15
|
-
* Read the steps state for a project
|
|
17
|
+
* Read the steps state for a project context.
|
|
16
18
|
*/
|
|
17
|
-
export async function readSteps(projectName, iteration) {
|
|
19
|
+
export async function readSteps(projectName, iteration, contextDir) {
|
|
18
20
|
try {
|
|
19
|
-
const content = await readFile(stepsPath(projectName, iteration), 'utf-8');
|
|
21
|
+
const content = await readFile(stepsPath(projectName, iteration, contextDir), 'utf-8');
|
|
20
22
|
const data = JSON.parse(content);
|
|
21
23
|
return data.docs ?? {};
|
|
22
24
|
}
|
|
@@ -27,8 +29,8 @@ export async function readSteps(projectName, iteration) {
|
|
|
27
29
|
/**
|
|
28
30
|
* Write steps state to disk.
|
|
29
31
|
*/
|
|
30
|
-
async function writeSteps(projectName, iteration, docs) {
|
|
31
|
-
const filePath = stepsPath(projectName, iteration);
|
|
32
|
+
async function writeSteps(projectName, iteration, docs, contextDir) {
|
|
33
|
+
const filePath = stepsPath(projectName, iteration, contextDir);
|
|
32
34
|
await mkdir(dirname(filePath), { recursive: true });
|
|
33
35
|
const data = { docs };
|
|
34
36
|
await writeFile(filePath, JSON.stringify(data, null, 2) + '\n', 'utf-8');
|
|
@@ -36,8 +38,8 @@ async function writeSteps(projectName, iteration, docs) {
|
|
|
36
38
|
/**
|
|
37
39
|
* Get the step state for a specific document.
|
|
38
40
|
*/
|
|
39
|
-
export async function getDocStepState(projectName, iteration, docId) {
|
|
40
|
-
const docs = await readSteps(projectName, iteration);
|
|
41
|
+
export async function getDocStepState(projectName, iteration, docId, contextDir) {
|
|
42
|
+
const docs = await readSteps(projectName, iteration, contextDir);
|
|
41
43
|
return docs[docId] ?? null;
|
|
42
44
|
}
|
|
43
45
|
/**
|
|
@@ -54,8 +56,8 @@ export function getCompletedStepIds(state) {
|
|
|
54
56
|
*
|
|
55
57
|
* @returns The updated DocStepState
|
|
56
58
|
*/
|
|
57
|
-
export async function recordStepCompletion(projectName, iteration, docId, stepId, artifactPath, allStepIds) {
|
|
58
|
-
const docs = await readSteps(projectName, iteration);
|
|
59
|
+
export async function recordStepCompletion(projectName, iteration, docId, stepId, artifactPath, allStepIds, contextDir) {
|
|
60
|
+
const docs = await readSteps(projectName, iteration, contextDir);
|
|
59
61
|
let state = docs[docId];
|
|
60
62
|
if (!state) {
|
|
61
63
|
state = {
|
|
@@ -86,28 +88,28 @@ export async function recordStepCompletion(projectName, iteration, docId, stepId
|
|
|
86
88
|
};
|
|
87
89
|
state.completedSteps.push(record);
|
|
88
90
|
docs[docId] = state;
|
|
89
|
-
await writeSteps(projectName, iteration, docs);
|
|
91
|
+
await writeSteps(projectName, iteration, docs, contextDir);
|
|
90
92
|
return state;
|
|
91
93
|
}
|
|
92
94
|
/**
|
|
93
95
|
* Mark a document as finalized (all steps completed + final doc written).
|
|
94
96
|
*/
|
|
95
|
-
export async function markFinalized(projectName, iteration, docId) {
|
|
96
|
-
const docs = await readSteps(projectName, iteration);
|
|
97
|
+
export async function markFinalized(projectName, iteration, docId, contextDir) {
|
|
98
|
+
const docs = await readSteps(projectName, iteration, contextDir);
|
|
97
99
|
const state = docs[docId];
|
|
98
100
|
if (!state) {
|
|
99
101
|
throw new Error(`No step state found for document "${docId}"`);
|
|
100
102
|
}
|
|
101
103
|
state.finalized = true;
|
|
102
104
|
state.finalizedAt = new Date().toISOString();
|
|
103
|
-
await writeSteps(projectName, iteration, docs);
|
|
105
|
+
await writeSteps(projectName, iteration, docs, contextDir);
|
|
104
106
|
return state;
|
|
105
107
|
}
|
|
106
108
|
/**
|
|
107
109
|
* Check if a document's sequential process is finalized.
|
|
108
110
|
*/
|
|
109
|
-
export async function isDocFinalized(projectName, iteration, docId) {
|
|
110
|
-
const state = await getDocStepState(projectName, iteration, docId);
|
|
111
|
+
export async function isDocFinalized(projectName, iteration, docId, contextDir) {
|
|
112
|
+
const state = await getDocStepState(projectName, iteration, docId, contextDir);
|
|
111
113
|
return state?.finalized ?? false;
|
|
112
114
|
}
|
|
113
115
|
//# sourceMappingURL=steps.js.map
|