@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/dispatch.d.ts
CHANGED
|
@@ -1,41 +1,44 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Dispatch & Session tracking — manages:
|
|
3
|
-
* <
|
|
4
|
-
* <
|
|
3
|
+
* <context_dir>/sessions.json
|
|
4
|
+
* <context_dir>/dispatches.json
|
|
5
|
+
*
|
|
6
|
+
* context_dir is typically iter-<n>/ or patch-<n>/ under the project data dir.
|
|
7
|
+
* All public functions accept an optional contextDir parameter.
|
|
5
8
|
*
|
|
6
9
|
* Sessions represent agent instances (can be reused across dispatches).
|
|
7
10
|
* Dispatches represent individual task assignments to a role.
|
|
8
11
|
* Relationship: Session 1:N Dispatch (a persistent session can receive multiple dispatches).
|
|
9
12
|
*/
|
|
10
13
|
import type { AgentType, SessionRecord, SessionStatus, DispatchRecord, DispatchStatus } from './types.js';
|
|
11
|
-
export declare function readSessions(projectName: string, iteration: number): Promise<SessionRecord[]>;
|
|
12
|
-
export declare function createSession(projectName: string, iteration: number, role: string, agentType?: AgentType, label?: string): Promise<SessionRecord>;
|
|
14
|
+
export declare function readSessions(projectName: string, iteration: number, contextDir?: string): Promise<SessionRecord[]>;
|
|
15
|
+
export declare function createSession(projectName: string, iteration: number, role: string, agentType?: AgentType, label?: string, contextDir?: string): Promise<SessionRecord>;
|
|
13
16
|
export declare function updateSession(projectName: string, iteration: number, sessionId: string, updates: {
|
|
14
17
|
status?: SessionStatus;
|
|
15
18
|
agentSessionId?: string;
|
|
16
19
|
agentType?: AgentType;
|
|
17
20
|
label?: string;
|
|
18
|
-
}): Promise<SessionRecord>;
|
|
21
|
+
}, contextDir?: string): Promise<SessionRecord>;
|
|
19
22
|
/**
|
|
20
23
|
* Find an idle session for a given role (for session reuse).
|
|
21
24
|
* Returns the most recently active idle session, or null if none found.
|
|
22
25
|
*/
|
|
23
|
-
export declare function findIdleSession(projectName: string, iteration: number, role: string): Promise<SessionRecord | null>;
|
|
26
|
+
export declare function findIdleSession(projectName: string, iteration: number, role: string, contextDir?: string): Promise<SessionRecord | null>;
|
|
24
27
|
/**
|
|
25
28
|
* Find a session by its agent session ID (for correlating external sessions).
|
|
26
29
|
*/
|
|
27
|
-
export declare function findSessionByAgentId(projectName: string, iteration: number, role: string, agentSessionId: string): Promise<SessionRecord | null>;
|
|
28
|
-
export declare function readDispatches(projectName: string, iteration: number): Promise<DispatchRecord[]>;
|
|
29
|
-
export declare function createDispatch(projectName: string, iteration: number, role: string, taskBrief: string, expectedOutputs: string[], sessionId?: string): Promise<DispatchRecord>;
|
|
30
|
+
export declare function findSessionByAgentId(projectName: string, iteration: number, role: string, agentSessionId: string, contextDir?: string): Promise<SessionRecord | null>;
|
|
31
|
+
export declare function readDispatches(projectName: string, iteration: number, contextDir?: string): Promise<DispatchRecord[]>;
|
|
32
|
+
export declare function createDispatch(projectName: string, iteration: number, role: string, taskBrief: string, expectedOutputs: string[], sessionId?: string, contextDir?: string): Promise<DispatchRecord>;
|
|
30
33
|
export declare function updateDispatch(projectName: string, iteration: number, dispatchId: string, updates: {
|
|
31
34
|
status?: DispatchStatus;
|
|
32
35
|
sessionId?: string;
|
|
33
36
|
note?: string;
|
|
34
|
-
}): Promise<DispatchRecord>;
|
|
37
|
+
}, contextDir?: string): Promise<DispatchRecord>;
|
|
35
38
|
/**
|
|
36
39
|
* Get a single dispatch record by ID.
|
|
37
40
|
*/
|
|
38
|
-
export declare function getDispatch(projectName: string, iteration: number, dispatchId: string): Promise<DispatchRecord | null>;
|
|
41
|
+
export declare function getDispatch(projectName: string, iteration: number, dispatchId: string, contextDir?: string): Promise<DispatchRecord | null>;
|
|
39
42
|
/** Valid state transitions for dispatch status. */
|
|
40
43
|
export declare const DISPATCH_TRANSITIONS: Record<DispatchStatus, DispatchStatus[]>;
|
|
41
44
|
/**
|
package/build/core/dispatch.js
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Dispatch & Session tracking — manages:
|
|
3
|
-
* <
|
|
4
|
-
* <
|
|
3
|
+
* <context_dir>/sessions.json
|
|
4
|
+
* <context_dir>/dispatches.json
|
|
5
|
+
*
|
|
6
|
+
* context_dir is typically iter-<n>/ or patch-<n>/ under the project data dir.
|
|
7
|
+
* All public functions accept an optional contextDir parameter.
|
|
5
8
|
*
|
|
6
9
|
* Sessions represent agent instances (can be reused across dispatches).
|
|
7
10
|
* Dispatches represent individual task assignments to a role.
|
|
@@ -12,24 +15,26 @@ import { join, dirname } from 'node:path';
|
|
|
12
15
|
import { getIterationDir } from './registry.js';
|
|
13
16
|
const SESSIONS_FILE = 'sessions.json';
|
|
14
17
|
const DISPATCHES_FILE = 'dispatches.json';
|
|
15
|
-
function sessionsPath(projectName, iteration) {
|
|
16
|
-
|
|
18
|
+
function sessionsPath(projectName, iteration, contextDir) {
|
|
19
|
+
const base = contextDir ?? getIterationDir(projectName, iteration);
|
|
20
|
+
return join(base, SESSIONS_FILE);
|
|
17
21
|
}
|
|
18
|
-
function dispatchesPath(projectName, iteration) {
|
|
19
|
-
|
|
22
|
+
function dispatchesPath(projectName, iteration, contextDir) {
|
|
23
|
+
const base = contextDir ?? getIterationDir(projectName, iteration);
|
|
24
|
+
return join(base, DISPATCHES_FILE);
|
|
20
25
|
}
|
|
21
26
|
// ─── Session CRUD ───
|
|
22
|
-
export async function readSessions(projectName, iteration) {
|
|
27
|
+
export async function readSessions(projectName, iteration, contextDir) {
|
|
23
28
|
try {
|
|
24
|
-
const content = await readFile(sessionsPath(projectName, iteration), 'utf-8');
|
|
29
|
+
const content = await readFile(sessionsPath(projectName, iteration, contextDir), 'utf-8');
|
|
25
30
|
return JSON.parse(content);
|
|
26
31
|
}
|
|
27
32
|
catch {
|
|
28
33
|
return [];
|
|
29
34
|
}
|
|
30
35
|
}
|
|
31
|
-
async function writeSessions(projectName, iteration, sessions) {
|
|
32
|
-
const filePath = sessionsPath(projectName, iteration);
|
|
36
|
+
async function writeSessions(projectName, iteration, sessions, contextDir) {
|
|
37
|
+
const filePath = sessionsPath(projectName, iteration, contextDir);
|
|
33
38
|
await mkdir(dirname(filePath), { recursive: true });
|
|
34
39
|
await writeFile(filePath, JSON.stringify(sessions, null, 2) + '\n', 'utf-8');
|
|
35
40
|
}
|
|
@@ -37,8 +42,8 @@ function nextSessionId(sessions) {
|
|
|
37
42
|
const num = sessions.length + 1;
|
|
38
43
|
return `ses-${String(num).padStart(3, '0')}`;
|
|
39
44
|
}
|
|
40
|
-
export async function createSession(projectName, iteration, role, agentType, label) {
|
|
41
|
-
const sessions = await readSessions(projectName, iteration);
|
|
45
|
+
export async function createSession(projectName, iteration, role, agentType, label, contextDir) {
|
|
46
|
+
const sessions = await readSessions(projectName, iteration, contextDir);
|
|
42
47
|
const now = new Date().toISOString();
|
|
43
48
|
const session = {
|
|
44
49
|
id: nextSessionId(sessions),
|
|
@@ -50,11 +55,11 @@ export async function createSession(projectName, iteration, role, agentType, lab
|
|
|
50
55
|
lastActiveAt: now,
|
|
51
56
|
};
|
|
52
57
|
sessions.push(session);
|
|
53
|
-
await writeSessions(projectName, iteration, sessions);
|
|
58
|
+
await writeSessions(projectName, iteration, sessions, contextDir);
|
|
54
59
|
return session;
|
|
55
60
|
}
|
|
56
|
-
export async function updateSession(projectName, iteration, sessionId, updates) {
|
|
57
|
-
const sessions = await readSessions(projectName, iteration);
|
|
61
|
+
export async function updateSession(projectName, iteration, sessionId, updates, contextDir) {
|
|
62
|
+
const sessions = await readSessions(projectName, iteration, contextDir);
|
|
58
63
|
const session = sessions.find((s) => s.id === sessionId);
|
|
59
64
|
if (!session) {
|
|
60
65
|
throw new Error(`Session "${sessionId}" not found in project "${projectName}"`);
|
|
@@ -68,15 +73,15 @@ export async function updateSession(projectName, iteration, sessionId, updates)
|
|
|
68
73
|
if (updates.label !== undefined)
|
|
69
74
|
session.label = updates.label;
|
|
70
75
|
session.lastActiveAt = new Date().toISOString();
|
|
71
|
-
await writeSessions(projectName, iteration, sessions);
|
|
76
|
+
await writeSessions(projectName, iteration, sessions, contextDir);
|
|
72
77
|
return session;
|
|
73
78
|
}
|
|
74
79
|
/**
|
|
75
80
|
* Find an idle session for a given role (for session reuse).
|
|
76
81
|
* Returns the most recently active idle session, or null if none found.
|
|
77
82
|
*/
|
|
78
|
-
export async function findIdleSession(projectName, iteration, role) {
|
|
79
|
-
const sessions = await readSessions(projectName, iteration);
|
|
83
|
+
export async function findIdleSession(projectName, iteration, role, contextDir) {
|
|
84
|
+
const sessions = await readSessions(projectName, iteration, contextDir);
|
|
80
85
|
const idle = sessions
|
|
81
86
|
.filter((s) => s.role === role && s.status === 'idle')
|
|
82
87
|
.sort((a, b) => b.lastActiveAt.localeCompare(a.lastActiveAt));
|
|
@@ -85,22 +90,22 @@ export async function findIdleSession(projectName, iteration, role) {
|
|
|
85
90
|
/**
|
|
86
91
|
* Find a session by its agent session ID (for correlating external sessions).
|
|
87
92
|
*/
|
|
88
|
-
export async function findSessionByAgentId(projectName, iteration, role, agentSessionId) {
|
|
89
|
-
const sessions = await readSessions(projectName, iteration);
|
|
93
|
+
export async function findSessionByAgentId(projectName, iteration, role, agentSessionId, contextDir) {
|
|
94
|
+
const sessions = await readSessions(projectName, iteration, contextDir);
|
|
90
95
|
return sessions.find((s) => s.role === role && s.agentSessionId === agentSessionId) ?? null;
|
|
91
96
|
}
|
|
92
97
|
// ─── Dispatch CRUD ───
|
|
93
|
-
export async function readDispatches(projectName, iteration) {
|
|
98
|
+
export async function readDispatches(projectName, iteration, contextDir) {
|
|
94
99
|
try {
|
|
95
|
-
const content = await readFile(dispatchesPath(projectName, iteration), 'utf-8');
|
|
100
|
+
const content = await readFile(dispatchesPath(projectName, iteration, contextDir), 'utf-8');
|
|
96
101
|
return JSON.parse(content);
|
|
97
102
|
}
|
|
98
103
|
catch {
|
|
99
104
|
return [];
|
|
100
105
|
}
|
|
101
106
|
}
|
|
102
|
-
async function writeDispatches(projectName, iteration, dispatches) {
|
|
103
|
-
const filePath = dispatchesPath(projectName, iteration);
|
|
107
|
+
async function writeDispatches(projectName, iteration, dispatches, contextDir) {
|
|
108
|
+
const filePath = dispatchesPath(projectName, iteration, contextDir);
|
|
104
109
|
await mkdir(dirname(filePath), { recursive: true });
|
|
105
110
|
await writeFile(filePath, JSON.stringify(dispatches, null, 2) + '\n', 'utf-8');
|
|
106
111
|
}
|
|
@@ -108,8 +113,8 @@ function nextDispatchId(dispatches) {
|
|
|
108
113
|
const num = dispatches.length + 1;
|
|
109
114
|
return `dispatch-${String(num).padStart(3, '0')}`;
|
|
110
115
|
}
|
|
111
|
-
export async function createDispatch(projectName, iteration, role, taskBrief, expectedOutputs, sessionId) {
|
|
112
|
-
const dispatches = await readDispatches(projectName, iteration);
|
|
116
|
+
export async function createDispatch(projectName, iteration, role, taskBrief, expectedOutputs, sessionId, contextDir) {
|
|
117
|
+
const dispatches = await readDispatches(projectName, iteration, contextDir);
|
|
113
118
|
const now = new Date().toISOString();
|
|
114
119
|
const dispatch = {
|
|
115
120
|
id: nextDispatchId(dispatches),
|
|
@@ -122,11 +127,11 @@ export async function createDispatch(projectName, iteration, role, taskBrief, ex
|
|
|
122
127
|
...(sessionId ? { sessionId } : {}),
|
|
123
128
|
};
|
|
124
129
|
dispatches.push(dispatch);
|
|
125
|
-
await writeDispatches(projectName, iteration, dispatches);
|
|
130
|
+
await writeDispatches(projectName, iteration, dispatches, contextDir);
|
|
126
131
|
return dispatch;
|
|
127
132
|
}
|
|
128
|
-
export async function updateDispatch(projectName, iteration, dispatchId, updates) {
|
|
129
|
-
const dispatches = await readDispatches(projectName, iteration);
|
|
133
|
+
export async function updateDispatch(projectName, iteration, dispatchId, updates, contextDir) {
|
|
134
|
+
const dispatches = await readDispatches(projectName, iteration, contextDir);
|
|
130
135
|
const dispatch = dispatches.find((d) => d.id === dispatchId);
|
|
131
136
|
if (!dispatch) {
|
|
132
137
|
throw new Error(`Dispatch "${dispatchId}" not found in project "${projectName}"`);
|
|
@@ -143,14 +148,14 @@ export async function updateDispatch(projectName, iteration, dispatchId, updates
|
|
|
143
148
|
if (updates.note !== undefined)
|
|
144
149
|
dispatch.note = updates.note;
|
|
145
150
|
dispatch.updatedAt = now;
|
|
146
|
-
await writeDispatches(projectName, iteration, dispatches);
|
|
151
|
+
await writeDispatches(projectName, iteration, dispatches, contextDir);
|
|
147
152
|
return dispatch;
|
|
148
153
|
}
|
|
149
154
|
/**
|
|
150
155
|
* Get a single dispatch record by ID.
|
|
151
156
|
*/
|
|
152
|
-
export async function getDispatch(projectName, iteration, dispatchId) {
|
|
153
|
-
const dispatches = await readDispatches(projectName, iteration);
|
|
157
|
+
export async function getDispatch(projectName, iteration, dispatchId, contextDir) {
|
|
158
|
+
const dispatches = await readDispatches(projectName, iteration, contextDir);
|
|
154
159
|
return dispatches.find((d) => d.id === dispatchId) ?? null;
|
|
155
160
|
}
|
|
156
161
|
// ─── Dispatch State Machine ───
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dispatch.js","sourceRoot":"","sources":["../../src/core/dispatch.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"dispatch.js","sourceRoot":"","sources":["../../src/core/dispatch.ts"],"names":[],"mappings":"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"}
|
package/build/core/docs.d.ts
CHANGED
|
@@ -1,32 +1,36 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Document management — read/write files under <
|
|
2
|
+
* Document management — read/write files under <context_dir>/docs/
|
|
3
|
+
*
|
|
4
|
+
* context_dir is typically iter-<n>/ or patch-<n>/ under the project data dir.
|
|
5
|
+
* All public functions accept an optional contextDir parameter. When omitted,
|
|
6
|
+
* falls back to getIterationDir(projectName, iteration) for backward compat.
|
|
3
7
|
*
|
|
4
8
|
* Supports both .md and .html files based on doc format configuration.
|
|
5
9
|
* Also supports step artifact files for sequential mode (e.g. prd.requirements.json).
|
|
6
10
|
*/
|
|
7
11
|
import type { DocDefinition } from './types.js';
|
|
8
12
|
/**
|
|
9
|
-
* Write a document to <
|
|
13
|
+
* Write a document to <context_dir>/docs/<docId>.<ext>
|
|
10
14
|
*/
|
|
11
|
-
export declare function writeDoc(projectName: string, iteration: number, docId: string, content: string, docDef?: DocDefinition): Promise<string>;
|
|
15
|
+
export declare function writeDoc(projectName: string, iteration: number, docId: string, content: string, docDef?: DocDefinition, contextDir?: string): Promise<string>;
|
|
12
16
|
/**
|
|
13
|
-
* Read a document from <
|
|
17
|
+
* Read a document from <context_dir>/docs/<docId>.<ext>
|
|
14
18
|
* Tries both .md and .html extensions.
|
|
15
19
|
*/
|
|
16
|
-
export declare function readDoc(projectName: string, iteration: number, docId: string): Promise<string>;
|
|
20
|
+
export declare function readDoc(projectName: string, iteration: number, docId: string, contextDir?: string): Promise<string>;
|
|
17
21
|
/**
|
|
18
|
-
* List all documents in <
|
|
22
|
+
* List all documents in <context_dir>/docs/
|
|
19
23
|
*/
|
|
20
|
-
export declare function listDocs(projectName: string, iteration: number): Promise<string[]>;
|
|
24
|
+
export declare function listDocs(projectName: string, iteration: number, contextDir?: string): Promise<string[]>;
|
|
21
25
|
/**
|
|
22
|
-
* Write a step artifact to <
|
|
26
|
+
* Write a step artifact to <context_dir>/docs/<docId>.<stepId>.<ext>
|
|
23
27
|
*
|
|
24
28
|
* @param format - "json" or "md" (determines file extension)
|
|
25
29
|
* @returns The file path written
|
|
26
30
|
*/
|
|
27
|
-
export declare function writeStepArtifact(projectName: string, iteration: number, docId: string, stepId: string, content: string, format: 'json' | 'md'): Promise<string>;
|
|
31
|
+
export declare function writeStepArtifact(projectName: string, iteration: number, docId: string, stepId: string, content: string, format: 'json' | 'md', contextDir?: string): Promise<string>;
|
|
28
32
|
/**
|
|
29
|
-
* Read a step artifact from <
|
|
33
|
+
* Read a step artifact from <context_dir>/docs/<docId>.<stepId>.<ext>
|
|
30
34
|
* Tries .json first, then .md.
|
|
31
35
|
*/
|
|
32
|
-
export declare function readStepArtifact(projectName: string, iteration: number, docId: string, stepId: string): Promise<string>;
|
|
36
|
+
export declare function readStepArtifact(projectName: string, iteration: number, docId: string, stepId: string, contextDir?: string): Promise<string>;
|
package/build/core/docs.js
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Document management — read/write files under <
|
|
2
|
+
* Document management — read/write files under <context_dir>/docs/
|
|
3
|
+
*
|
|
4
|
+
* context_dir is typically iter-<n>/ or patch-<n>/ under the project data dir.
|
|
5
|
+
* All public functions accept an optional contextDir parameter. When omitted,
|
|
6
|
+
* falls back to getIterationDir(projectName, iteration) for backward compat.
|
|
3
7
|
*
|
|
4
8
|
* Supports both .md and .html files based on doc format configuration.
|
|
5
9
|
* Also supports step artifact files for sequential mode (e.g. prd.requirements.json).
|
|
@@ -7,8 +11,9 @@
|
|
|
7
11
|
import { mkdir, readFile, writeFile, readdir } from 'node:fs/promises';
|
|
8
12
|
import { join } from 'node:path';
|
|
9
13
|
import { getIterationDir } from './registry.js';
|
|
10
|
-
function docsDir(projectName, iteration) {
|
|
11
|
-
|
|
14
|
+
function docsDir(projectName, iteration, contextDir) {
|
|
15
|
+
const base = contextDir ?? getIterationDir(projectName, iteration);
|
|
16
|
+
return join(base, 'docs');
|
|
12
17
|
}
|
|
13
18
|
/**
|
|
14
19
|
* Get file extension for a doc based on its definition.
|
|
@@ -17,10 +22,10 @@ function getDocExtension(docDef) {
|
|
|
17
22
|
return docDef?.format === 'html' ? '.html' : '.md';
|
|
18
23
|
}
|
|
19
24
|
/**
|
|
20
|
-
* Write a document to <
|
|
25
|
+
* Write a document to <context_dir>/docs/<docId>.<ext>
|
|
21
26
|
*/
|
|
22
|
-
export async function writeDoc(projectName, iteration, docId, content, docDef) {
|
|
23
|
-
const dir = docsDir(projectName, iteration);
|
|
27
|
+
export async function writeDoc(projectName, iteration, docId, content, docDef, contextDir) {
|
|
28
|
+
const dir = docsDir(projectName, iteration, contextDir);
|
|
24
29
|
await mkdir(dir, { recursive: true });
|
|
25
30
|
const ext = getDocExtension(docDef);
|
|
26
31
|
const filePath = join(dir, `${docId}${ext}`);
|
|
@@ -28,11 +33,11 @@ export async function writeDoc(projectName, iteration, docId, content, docDef) {
|
|
|
28
33
|
return filePath;
|
|
29
34
|
}
|
|
30
35
|
/**
|
|
31
|
-
* Read a document from <
|
|
36
|
+
* Read a document from <context_dir>/docs/<docId>.<ext>
|
|
32
37
|
* Tries both .md and .html extensions.
|
|
33
38
|
*/
|
|
34
|
-
export async function readDoc(projectName, iteration, docId) {
|
|
35
|
-
const dir = docsDir(projectName, iteration);
|
|
39
|
+
export async function readDoc(projectName, iteration, docId, contextDir) {
|
|
40
|
+
const dir = docsDir(projectName, iteration, contextDir);
|
|
36
41
|
// Try .md first, then .html
|
|
37
42
|
for (const ext of ['.md', '.html']) {
|
|
38
43
|
try {
|
|
@@ -45,10 +50,10 @@ export async function readDoc(projectName, iteration, docId) {
|
|
|
45
50
|
throw new Error(`Document "${docId}" not found`);
|
|
46
51
|
}
|
|
47
52
|
/**
|
|
48
|
-
* List all documents in <
|
|
53
|
+
* List all documents in <context_dir>/docs/
|
|
49
54
|
*/
|
|
50
|
-
export async function listDocs(projectName, iteration) {
|
|
51
|
-
const dir = docsDir(projectName, iteration);
|
|
55
|
+
export async function listDocs(projectName, iteration, contextDir) {
|
|
56
|
+
const dir = docsDir(projectName, iteration, contextDir);
|
|
52
57
|
try {
|
|
53
58
|
const files = await readdir(dir);
|
|
54
59
|
return files.filter((f) => f.endsWith('.md') || f.endsWith('.html')).map((f) => f.replace(/\.(md|html)$/, ''));
|
|
@@ -59,13 +64,13 @@ export async function listDocs(projectName, iteration) {
|
|
|
59
64
|
}
|
|
60
65
|
// ─── Step Artifact I/O ───
|
|
61
66
|
/**
|
|
62
|
-
* Write a step artifact to <
|
|
67
|
+
* Write a step artifact to <context_dir>/docs/<docId>.<stepId>.<ext>
|
|
63
68
|
*
|
|
64
69
|
* @param format - "json" or "md" (determines file extension)
|
|
65
70
|
* @returns The file path written
|
|
66
71
|
*/
|
|
67
|
-
export async function writeStepArtifact(projectName, iteration, docId, stepId, content, format) {
|
|
68
|
-
const dir = docsDir(projectName, iteration);
|
|
72
|
+
export async function writeStepArtifact(projectName, iteration, docId, stepId, content, format, contextDir) {
|
|
73
|
+
const dir = docsDir(projectName, iteration, contextDir);
|
|
69
74
|
await mkdir(dir, { recursive: true });
|
|
70
75
|
const ext = format === 'json' ? '.json' : '.md';
|
|
71
76
|
const filePath = join(dir, `${docId}.${stepId}${ext}`);
|
|
@@ -73,11 +78,11 @@ export async function writeStepArtifact(projectName, iteration, docId, stepId, c
|
|
|
73
78
|
return filePath;
|
|
74
79
|
}
|
|
75
80
|
/**
|
|
76
|
-
* Read a step artifact from <
|
|
81
|
+
* Read a step artifact from <context_dir>/docs/<docId>.<stepId>.<ext>
|
|
77
82
|
* Tries .json first, then .md.
|
|
78
83
|
*/
|
|
79
|
-
export async function readStepArtifact(projectName, iteration, docId, stepId) {
|
|
80
|
-
const dir = docsDir(projectName, iteration);
|
|
84
|
+
export async function readStepArtifact(projectName, iteration, docId, stepId, contextDir) {
|
|
85
|
+
const dir = docsDir(projectName, iteration, contextDir);
|
|
81
86
|
for (const ext of ['.json', '.md']) {
|
|
82
87
|
try {
|
|
83
88
|
return await readFile(join(dir, `${docId}.${stepId}${ext}`), 'utf-8');
|
package/build/core/docs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"docs.js","sourceRoot":"","sources":["../../src/core/docs.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"docs.js","sourceRoot":"","sources":["../../src/core/docs.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Issue tracking — manages <data_dir>/<project_name>/issues.json
|
|
3
|
+
*
|
|
4
|
+
* Issues are project-level (not per-iteration/patch). They track problems
|
|
5
|
+
* discovered during testing or from user feedback, and can be linked to
|
|
6
|
+
* the patch or iteration that resolves them.
|
|
7
|
+
*/
|
|
8
|
+
import type { Issue, IssueResolvedBy, IssueSource, IssueStatus } from './types.js';
|
|
9
|
+
/**
|
|
10
|
+
* Read all issues for a project. Returns empty array if file doesn't exist.
|
|
11
|
+
*/
|
|
12
|
+
export declare function readIssues(projectName: string): Promise<Issue[]>;
|
|
13
|
+
/**
|
|
14
|
+
* Create a new issue. Auto-generates an incremental ID.
|
|
15
|
+
*
|
|
16
|
+
* @returns The created issue
|
|
17
|
+
*/
|
|
18
|
+
export declare function createIssue(projectName: string, title: string, description: string, source: IssueSource, iteration: number): Promise<Issue>;
|
|
19
|
+
/**
|
|
20
|
+
* Update an existing issue.
|
|
21
|
+
* Supports partial updates: status, resolvedBy, closedAt.
|
|
22
|
+
*
|
|
23
|
+
* @returns The updated issue
|
|
24
|
+
*/
|
|
25
|
+
export declare function updateIssue(projectName: string, issueId: string, updates: {
|
|
26
|
+
status?: IssueStatus;
|
|
27
|
+
resolvedBy?: IssueResolvedBy;
|
|
28
|
+
}): Promise<Issue>;
|
|
29
|
+
export interface IssueFilters {
|
|
30
|
+
status?: IssueStatus;
|
|
31
|
+
source?: IssueSource;
|
|
32
|
+
iteration?: number;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* List issues with optional filters.
|
|
36
|
+
*/
|
|
37
|
+
export declare function listIssues(projectName: string, filters?: IssueFilters): Promise<Issue[]>;
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Issue tracking — manages <data_dir>/<project_name>/issues.json
|
|
3
|
+
*
|
|
4
|
+
* Issues are project-level (not per-iteration/patch). They track problems
|
|
5
|
+
* discovered during testing or from user feedback, and can be linked to
|
|
6
|
+
* the patch or iteration that resolves them.
|
|
7
|
+
*/
|
|
8
|
+
import { readFile, writeFile } from 'node:fs/promises';
|
|
9
|
+
import { join } from 'node:path';
|
|
10
|
+
import { getProjectDataDir } from './registry.js';
|
|
11
|
+
const ISSUES_FILE = 'issues.json';
|
|
12
|
+
function issuesPath(projectName) {
|
|
13
|
+
return join(getProjectDataDir(projectName), ISSUES_FILE);
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Read all issues for a project. Returns empty array if file doesn't exist.
|
|
17
|
+
*/
|
|
18
|
+
export async function readIssues(projectName) {
|
|
19
|
+
try {
|
|
20
|
+
const content = await readFile(issuesPath(projectName), 'utf-8');
|
|
21
|
+
return JSON.parse(content);
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return [];
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Write issues array to disk.
|
|
29
|
+
*/
|
|
30
|
+
async function writeIssues(projectName, issues) {
|
|
31
|
+
await writeFile(issuesPath(projectName), JSON.stringify(issues, null, 2) + '\n', 'utf-8');
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Create a new issue. Auto-generates an incremental ID.
|
|
35
|
+
*
|
|
36
|
+
* @returns The created issue
|
|
37
|
+
*/
|
|
38
|
+
export async function createIssue(projectName, title, description, source, iteration) {
|
|
39
|
+
const issues = await readIssues(projectName);
|
|
40
|
+
// Generate next ID
|
|
41
|
+
const maxNum = issues.reduce((max, iss) => {
|
|
42
|
+
const match = iss.id.match(/^issue-(\d+)$/);
|
|
43
|
+
return match ? Math.max(max, parseInt(match[1], 10)) : max;
|
|
44
|
+
}, 0);
|
|
45
|
+
const issue = {
|
|
46
|
+
id: `issue-${maxNum + 1}`,
|
|
47
|
+
title,
|
|
48
|
+
description,
|
|
49
|
+
source,
|
|
50
|
+
iteration,
|
|
51
|
+
status: 'open',
|
|
52
|
+
createdAt: new Date().toISOString(),
|
|
53
|
+
};
|
|
54
|
+
issues.push(issue);
|
|
55
|
+
await writeIssues(projectName, issues);
|
|
56
|
+
return issue;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Update an existing issue.
|
|
60
|
+
* Supports partial updates: status, resolvedBy, closedAt.
|
|
61
|
+
*
|
|
62
|
+
* @returns The updated issue
|
|
63
|
+
*/
|
|
64
|
+
export async function updateIssue(projectName, issueId, updates) {
|
|
65
|
+
const issues = await readIssues(projectName);
|
|
66
|
+
const issue = issues.find((i) => i.id === issueId);
|
|
67
|
+
if (!issue) {
|
|
68
|
+
throw new Error(`Issue "${issueId}" not found.`);
|
|
69
|
+
}
|
|
70
|
+
if (updates.status !== undefined) {
|
|
71
|
+
issue.status = updates.status;
|
|
72
|
+
if (updates.status === 'closed') {
|
|
73
|
+
issue.closedAt = new Date().toISOString();
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
if (updates.resolvedBy !== undefined) {
|
|
77
|
+
issue.resolvedBy = updates.resolvedBy;
|
|
78
|
+
}
|
|
79
|
+
await writeIssues(projectName, issues);
|
|
80
|
+
return issue;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* List issues with optional filters.
|
|
84
|
+
*/
|
|
85
|
+
export async function listIssues(projectName, filters) {
|
|
86
|
+
let issues = await readIssues(projectName);
|
|
87
|
+
if (filters) {
|
|
88
|
+
if (filters.status) {
|
|
89
|
+
issues = issues.filter((i) => i.status === filters.status);
|
|
90
|
+
}
|
|
91
|
+
if (filters.source) {
|
|
92
|
+
issues = issues.filter((i) => i.source === filters.source);
|
|
93
|
+
}
|
|
94
|
+
if (filters.iteration !== undefined) {
|
|
95
|
+
issues = issues.filter((i) => i.iteration === filters.iteration);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return issues;
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=issues.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"issues.js","sourceRoot":"","sources":["../../src/core/issues.ts"],"names":[],"mappings":"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"}
|
package/build/core/registry.d.ts
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
|
*/
|
|
@@ -34,6 +39,12 @@ export interface ProjectEntry {
|
|
|
34
39
|
currentIteration: number;
|
|
35
40
|
/** Total number of iterations created so far */
|
|
36
41
|
totalIterations: number;
|
|
42
|
+
/** Currently active patch number (starts at 1, 0 means no patch started yet) */
|
|
43
|
+
currentPatch: number;
|
|
44
|
+
/** Total number of patches created so far */
|
|
45
|
+
totalPatches: number;
|
|
46
|
+
/** Active context identifier, e.g. "iter-1" or "patch-2". Empty string means no context. */
|
|
47
|
+
activeContext: string;
|
|
37
48
|
}
|
|
38
49
|
export interface Registry {
|
|
39
50
|
projects: Record<string, ProjectEntry>;
|
|
@@ -93,3 +104,26 @@ export declare function getIterationDir(projectName: string, iteration: number):
|
|
|
93
104
|
* @returns The new iteration number
|
|
94
105
|
*/
|
|
95
106
|
export declare function startIteration(projectName: string): Promise<number>;
|
|
107
|
+
/**
|
|
108
|
+
* Get the patch directory for a specific project patch.
|
|
109
|
+
* Pure path concatenation — does NOT check if the directory exists.
|
|
110
|
+
*/
|
|
111
|
+
export declare function getPatchDir(projectName: string, patch: number): string;
|
|
112
|
+
/**
|
|
113
|
+
* Start a new patch for a project.
|
|
114
|
+
* Creates the patch directory (with docs/ subdirectory) and updates the registry.
|
|
115
|
+
*
|
|
116
|
+
* @returns The new patch number
|
|
117
|
+
*/
|
|
118
|
+
export declare function startPatch(projectName: string): Promise<number>;
|
|
119
|
+
/**
|
|
120
|
+
* Resolve the active context directory for a project.
|
|
121
|
+
* Parses activeContext string (e.g. "iter-1", "patch-2") into an absolute path.
|
|
122
|
+
*
|
|
123
|
+
* @returns { dir: string, type: 'iteration' | 'patch', number: number } or null if no active context
|
|
124
|
+
*/
|
|
125
|
+
export declare function resolveContextDir(projectName: string, activeContext: string): {
|
|
126
|
+
dir: string;
|
|
127
|
+
type: 'iteration' | 'patch';
|
|
128
|
+
number: number;
|
|
129
|
+
} | null;
|