@lumenflow/core 1.3.0 → 1.3.3
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/arg-parser.d.ts +6 -0
- package/dist/arg-parser.js +16 -0
- package/dist/core/tool.schemas.d.ts +1 -1
- package/dist/coverage-gate.d.ts +3 -0
- package/dist/coverage-gate.js +7 -4
- package/dist/force-bypass-audit.d.ts +63 -0
- package/dist/force-bypass-audit.js +140 -0
- package/dist/gates-config.d.ts +132 -0
- package/dist/gates-config.js +229 -0
- package/dist/git-adapter.d.ts +7 -0
- package/dist/git-adapter.js +15 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.js +6 -0
- package/dist/lumenflow-config-schema.d.ts +97 -0
- package/dist/lumenflow-config-schema.js +9 -0
- package/dist/lumenflow-home.d.ts +130 -0
- package/dist/lumenflow-home.js +211 -0
- package/dist/manual-test-validator.d.ts +3 -0
- package/dist/manual-test-validator.js +7 -4
- package/dist/orphan-detector.d.ts +16 -0
- package/dist/orphan-detector.js +24 -0
- package/dist/prompt-linter.js +2 -1
- package/dist/prompt-monitor.js +3 -1
- package/dist/spec-branch-helpers.d.ts +118 -0
- package/dist/spec-branch-helpers.js +199 -0
- package/dist/user-normalizer.d.ts +5 -1
- package/dist/user-normalizer.js +6 -1
- package/dist/validators/phi-scanner.js +6 -0
- package/dist/worktree-symlink.d.ts +4 -0
- package/dist/worktree-symlink.js +14 -20
- package/dist/wu-consistency-checker.d.ts +2 -0
- package/dist/wu-consistency-checker.js +35 -1
- package/dist/wu-constants.d.ts +193 -0
- package/dist/wu-constants.js +200 -4
- package/dist/wu-create-validators.d.ts +57 -2
- package/dist/wu-create-validators.js +111 -2
- package/dist/wu-done-branch-only.js +9 -0
- package/dist/wu-done-docs-generate.d.ts +73 -0
- package/dist/wu-done-docs-generate.js +108 -0
- package/dist/wu-done-worktree.js +12 -0
- package/dist/wu-schema.js +3 -1
- package/dist/wu-spawn.js +15 -2
- package/dist/wu-yaml-fixer.js +6 -3
- package/package.json +12 -11
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Spec Branch Helpers
|
|
3
|
+
*
|
|
4
|
+
* WU-1062: External plan storage and no-main-write mode
|
|
5
|
+
*
|
|
6
|
+
* Provides helpers for working with spec branches (spec/wu-XXXX).
|
|
7
|
+
* wu:create writes to spec branches by default; wu:claim merges them to main.
|
|
8
|
+
*
|
|
9
|
+
* @module
|
|
10
|
+
*/
|
|
11
|
+
import type { GitAdapter } from './git-adapter.js';
|
|
12
|
+
/**
|
|
13
|
+
* Spec branch prefix
|
|
14
|
+
*/
|
|
15
|
+
export declare const SPEC_BRANCH_PREFIX = "spec/";
|
|
16
|
+
/**
|
|
17
|
+
* WU source location constants
|
|
18
|
+
*/
|
|
19
|
+
export declare const WU_SOURCE: {
|
|
20
|
+
/** WU exists on main branch only */
|
|
21
|
+
readonly MAIN: "main";
|
|
22
|
+
/** WU exists on spec branch only */
|
|
23
|
+
readonly SPEC_BRANCH: "spec_branch";
|
|
24
|
+
/** WU exists on both main and spec branch */
|
|
25
|
+
readonly BOTH: "both";
|
|
26
|
+
/** WU not found anywhere */
|
|
27
|
+
readonly NOT_FOUND: "not_found";
|
|
28
|
+
};
|
|
29
|
+
export type WUSourceType = (typeof WU_SOURCE)[keyof typeof WU_SOURCE];
|
|
30
|
+
/**
|
|
31
|
+
* Get the spec branch name for a WU
|
|
32
|
+
*
|
|
33
|
+
* @param {string} wuId - Work Unit ID (e.g., 'WU-1062')
|
|
34
|
+
* @returns {string} Spec branch name (e.g., 'spec/wu-1062')
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* getSpecBranchName('WU-1062') // 'spec/wu-1062'
|
|
38
|
+
*/
|
|
39
|
+
export declare function getSpecBranchName(wuId: string): string;
|
|
40
|
+
/**
|
|
41
|
+
* Get the origin-qualified spec branch name
|
|
42
|
+
*
|
|
43
|
+
* @param {string} wuId - Work Unit ID
|
|
44
|
+
* @returns {string} Origin-qualified branch name (e.g., 'origin/spec/wu-1062')
|
|
45
|
+
*/
|
|
46
|
+
export declare function getOriginSpecBranch(wuId: string): string;
|
|
47
|
+
/**
|
|
48
|
+
* Check if a spec branch exists on origin
|
|
49
|
+
*
|
|
50
|
+
* @param {string} wuId - Work Unit ID
|
|
51
|
+
* @param {SimpleGit} git - Git adapter instance
|
|
52
|
+
* @returns {Promise<boolean>} True if spec branch exists
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* const exists = await specBranchExists('WU-1062', git);
|
|
56
|
+
*/
|
|
57
|
+
export declare function specBranchExists(wuId: string, git: GitAdapter): Promise<boolean>;
|
|
58
|
+
/**
|
|
59
|
+
* Check if a WU exists on main branch
|
|
60
|
+
*
|
|
61
|
+
* @param {string} wuId - Work Unit ID
|
|
62
|
+
* @param {SimpleGit} git - Git adapter instance
|
|
63
|
+
* @returns {Promise<boolean>} True if WU YAML exists on main
|
|
64
|
+
*/
|
|
65
|
+
export declare function isWUOnMain(wuId: string, git: GitAdapter): Promise<boolean>;
|
|
66
|
+
/**
|
|
67
|
+
* Merge spec branch to main branch (fast-forward only)
|
|
68
|
+
*
|
|
69
|
+
* This is used by wu:claim when a WU exists only on a spec branch.
|
|
70
|
+
* The spec branch is merged to main before creating the worktree.
|
|
71
|
+
*
|
|
72
|
+
* @param {string} wuId - Work Unit ID
|
|
73
|
+
* @param {SimpleGit} git - Git adapter instance
|
|
74
|
+
* @throws {Error} If merge fails (e.g., due to conflicts)
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* await mergeSpecBranchToMain('WU-1062', git);
|
|
78
|
+
*/
|
|
79
|
+
export declare function mergeSpecBranchToMain(wuId: string, git: GitAdapter): Promise<void>;
|
|
80
|
+
/**
|
|
81
|
+
* Delete spec branch after merge
|
|
82
|
+
*
|
|
83
|
+
* @param {string} wuId - Work Unit ID
|
|
84
|
+
* @param {SimpleGit} git - Git adapter instance
|
|
85
|
+
*/
|
|
86
|
+
export declare function deleteSpecBranch(wuId: string, git: GitAdapter): Promise<void>;
|
|
87
|
+
/**
|
|
88
|
+
* Determine the source of a WU (main, spec branch, both, or not found)
|
|
89
|
+
*
|
|
90
|
+
* Used by wu:claim to decide whether to merge spec branch before creating worktree.
|
|
91
|
+
*
|
|
92
|
+
* @param {string} wuId - Work Unit ID
|
|
93
|
+
* @param {SimpleGit} git - Git adapter instance
|
|
94
|
+
* @returns {Promise<WUSourceType>} Source location constant
|
|
95
|
+
*
|
|
96
|
+
* @example
|
|
97
|
+
* const source = await getWUSource('WU-1062', git);
|
|
98
|
+
* if (source === WU_SOURCE.SPEC_BRANCH) {
|
|
99
|
+
* await mergeSpecBranchToMain('WU-1062', git);
|
|
100
|
+
* }
|
|
101
|
+
*/
|
|
102
|
+
export declare function getWUSource(wuId: string, git: GitAdapter): Promise<WUSourceType>;
|
|
103
|
+
/**
|
|
104
|
+
* Create a spec branch from current HEAD
|
|
105
|
+
*
|
|
106
|
+
* Used by wu:create in default mode (no --direct flag).
|
|
107
|
+
*
|
|
108
|
+
* @param {string} wuId - Work Unit ID
|
|
109
|
+
* @param {SimpleGit} git - Git adapter instance
|
|
110
|
+
*/
|
|
111
|
+
export declare function createSpecBranch(wuId: string, git: GitAdapter): Promise<void>;
|
|
112
|
+
/**
|
|
113
|
+
* Push spec branch to origin
|
|
114
|
+
*
|
|
115
|
+
* @param {string} wuId - Work Unit ID
|
|
116
|
+
* @param {SimpleGit} git - Git adapter instance
|
|
117
|
+
*/
|
|
118
|
+
export declare function pushSpecBranch(wuId: string, git: GitAdapter): Promise<void>;
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Spec Branch Helpers
|
|
3
|
+
*
|
|
4
|
+
* WU-1062: External plan storage and no-main-write mode
|
|
5
|
+
*
|
|
6
|
+
* Provides helpers for working with spec branches (spec/wu-XXXX).
|
|
7
|
+
* wu:create writes to spec branches by default; wu:claim merges them to main.
|
|
8
|
+
*
|
|
9
|
+
* @module
|
|
10
|
+
*/
|
|
11
|
+
import { WU_PATHS } from './wu-paths.js';
|
|
12
|
+
import { REMOTES, GIT_REFS, GIT_COMMANDS, GIT_FLAGS } from './wu-constants.js';
|
|
13
|
+
/**
|
|
14
|
+
* Spec branch prefix
|
|
15
|
+
*/
|
|
16
|
+
export const SPEC_BRANCH_PREFIX = 'spec/';
|
|
17
|
+
/**
|
|
18
|
+
* WU source location constants
|
|
19
|
+
*/
|
|
20
|
+
export const WU_SOURCE = {
|
|
21
|
+
/** WU exists on main branch only */
|
|
22
|
+
MAIN: 'main',
|
|
23
|
+
/** WU exists on spec branch only */
|
|
24
|
+
SPEC_BRANCH: 'spec_branch',
|
|
25
|
+
/** WU exists on both main and spec branch */
|
|
26
|
+
BOTH: 'both',
|
|
27
|
+
/** WU not found anywhere */
|
|
28
|
+
NOT_FOUND: 'not_found',
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Get the spec branch name for a WU
|
|
32
|
+
*
|
|
33
|
+
* @param {string} wuId - Work Unit ID (e.g., 'WU-1062')
|
|
34
|
+
* @returns {string} Spec branch name (e.g., 'spec/wu-1062')
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* getSpecBranchName('WU-1062') // 'spec/wu-1062'
|
|
38
|
+
*/
|
|
39
|
+
export function getSpecBranchName(wuId) {
|
|
40
|
+
return `${SPEC_BRANCH_PREFIX}${wuId.toLowerCase()}`;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Get the origin-qualified spec branch name
|
|
44
|
+
*
|
|
45
|
+
* @param {string} wuId - Work Unit ID
|
|
46
|
+
* @returns {string} Origin-qualified branch name (e.g., 'origin/spec/wu-1062')
|
|
47
|
+
*/
|
|
48
|
+
export function getOriginSpecBranch(wuId) {
|
|
49
|
+
return GIT_REFS.remote(REMOTES.ORIGIN, getSpecBranchName(wuId));
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Check if a spec branch exists on origin
|
|
53
|
+
*
|
|
54
|
+
* @param {string} wuId - Work Unit ID
|
|
55
|
+
* @param {SimpleGit} git - Git adapter instance
|
|
56
|
+
* @returns {Promise<boolean>} True if spec branch exists
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* const exists = await specBranchExists('WU-1062', git);
|
|
60
|
+
*/
|
|
61
|
+
export async function specBranchExists(wuId, git) {
|
|
62
|
+
try {
|
|
63
|
+
const originBranch = getOriginSpecBranch(wuId);
|
|
64
|
+
// Use branchExists if available, otherwise check with ls-remote
|
|
65
|
+
if ('branchExists' in git && typeof git.branchExists === 'function') {
|
|
66
|
+
return await git.branchExists(originBranch);
|
|
67
|
+
}
|
|
68
|
+
// Fallback: use ls-remote to check if branch exists
|
|
69
|
+
const result = await git.raw([
|
|
70
|
+
GIT_COMMANDS.LS_REMOTE,
|
|
71
|
+
GIT_FLAGS.HEADS,
|
|
72
|
+
REMOTES.ORIGIN,
|
|
73
|
+
getSpecBranchName(wuId),
|
|
74
|
+
]);
|
|
75
|
+
return result.trim().length > 0;
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Check if a WU exists on main branch
|
|
83
|
+
*
|
|
84
|
+
* @param {string} wuId - Work Unit ID
|
|
85
|
+
* @param {SimpleGit} git - Git adapter instance
|
|
86
|
+
* @returns {Promise<boolean>} True if WU YAML exists on main
|
|
87
|
+
*/
|
|
88
|
+
export async function isWUOnMain(wuId, git) {
|
|
89
|
+
try {
|
|
90
|
+
const wuPath = WU_PATHS.WU(wuId);
|
|
91
|
+
// Check if file exists on origin/main
|
|
92
|
+
// git ls-tree returns exit 0 with empty output if file doesn't exist
|
|
93
|
+
const result = await git.raw([GIT_COMMANDS.LS_TREE, GIT_REFS.ORIGIN_MAIN, GIT_FLAGS.PATH_SEPARATOR, wuPath]);
|
|
94
|
+
return result.trim().length > 0;
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Merge spec branch to main branch (fast-forward only)
|
|
102
|
+
*
|
|
103
|
+
* This is used by wu:claim when a WU exists only on a spec branch.
|
|
104
|
+
* The spec branch is merged to main before creating the worktree.
|
|
105
|
+
*
|
|
106
|
+
* @param {string} wuId - Work Unit ID
|
|
107
|
+
* @param {SimpleGit} git - Git adapter instance
|
|
108
|
+
* @throws {Error} If merge fails (e.g., due to conflicts)
|
|
109
|
+
*
|
|
110
|
+
* @example
|
|
111
|
+
* await mergeSpecBranchToMain('WU-1062', git);
|
|
112
|
+
*/
|
|
113
|
+
export async function mergeSpecBranchToMain(wuId, git) {
|
|
114
|
+
const specBranch = getSpecBranchName(wuId);
|
|
115
|
+
const originSpecBranch = getOriginSpecBranch(wuId);
|
|
116
|
+
// Fetch the spec branch
|
|
117
|
+
await git.fetch(REMOTES.ORIGIN, specBranch);
|
|
118
|
+
// Merge with fast-forward only (safe merge)
|
|
119
|
+
await git.merge(originSpecBranch, { ffOnly: true });
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Delete spec branch after merge
|
|
123
|
+
*
|
|
124
|
+
* @param {string} wuId - Work Unit ID
|
|
125
|
+
* @param {SimpleGit} git - Git adapter instance
|
|
126
|
+
*/
|
|
127
|
+
export async function deleteSpecBranch(wuId, git) {
|
|
128
|
+
const specBranch = getSpecBranchName(wuId);
|
|
129
|
+
try {
|
|
130
|
+
// Delete local branch if exists
|
|
131
|
+
await git.deleteBranch(specBranch);
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
// Ignore if local branch doesn't exist
|
|
135
|
+
}
|
|
136
|
+
try {
|
|
137
|
+
// Delete remote branch
|
|
138
|
+
await git.raw([GIT_COMMANDS.PUSH, REMOTES.ORIGIN, GIT_FLAGS.DELETE_REMOTE, specBranch]);
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
// Ignore if remote branch doesn't exist
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Determine the source of a WU (main, spec branch, both, or not found)
|
|
146
|
+
*
|
|
147
|
+
* Used by wu:claim to decide whether to merge spec branch before creating worktree.
|
|
148
|
+
*
|
|
149
|
+
* @param {string} wuId - Work Unit ID
|
|
150
|
+
* @param {SimpleGit} git - Git adapter instance
|
|
151
|
+
* @returns {Promise<WUSourceType>} Source location constant
|
|
152
|
+
*
|
|
153
|
+
* @example
|
|
154
|
+
* const source = await getWUSource('WU-1062', git);
|
|
155
|
+
* if (source === WU_SOURCE.SPEC_BRANCH) {
|
|
156
|
+
* await mergeSpecBranchToMain('WU-1062', git);
|
|
157
|
+
* }
|
|
158
|
+
*/
|
|
159
|
+
export async function getWUSource(wuId, git) {
|
|
160
|
+
// Check both locations in parallel for efficiency
|
|
161
|
+
const [onMain, hasSpecBranch] = await Promise.all([
|
|
162
|
+
isWUOnMain(wuId, git),
|
|
163
|
+
specBranchExists(wuId, git),
|
|
164
|
+
]);
|
|
165
|
+
if (onMain && hasSpecBranch) {
|
|
166
|
+
return WU_SOURCE.BOTH;
|
|
167
|
+
}
|
|
168
|
+
if (onMain) {
|
|
169
|
+
return WU_SOURCE.MAIN;
|
|
170
|
+
}
|
|
171
|
+
if (hasSpecBranch) {
|
|
172
|
+
return WU_SOURCE.SPEC_BRANCH;
|
|
173
|
+
}
|
|
174
|
+
return WU_SOURCE.NOT_FOUND;
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Create a spec branch from current HEAD
|
|
178
|
+
*
|
|
179
|
+
* Used by wu:create in default mode (no --direct flag).
|
|
180
|
+
*
|
|
181
|
+
* @param {string} wuId - Work Unit ID
|
|
182
|
+
* @param {SimpleGit} git - Git adapter instance
|
|
183
|
+
*/
|
|
184
|
+
export async function createSpecBranch(wuId, git) {
|
|
185
|
+
const specBranch = getSpecBranchName(wuId);
|
|
186
|
+
// Create local branch and checkout
|
|
187
|
+
await git.createBranch(specBranch);
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Push spec branch to origin
|
|
191
|
+
*
|
|
192
|
+
* @param {string} wuId - Work Unit ID
|
|
193
|
+
* @param {SimpleGit} git - Git adapter instance
|
|
194
|
+
*/
|
|
195
|
+
export async function pushSpecBranch(wuId, git) {
|
|
196
|
+
const specBranch = getSpecBranchName(wuId);
|
|
197
|
+
// Push to origin
|
|
198
|
+
await git.push(REMOTES.ORIGIN, specBranch);
|
|
199
|
+
}
|
|
@@ -4,11 +4,15 @@
|
|
|
4
4
|
* Provides email normalization and domain inference for WU ownership.
|
|
5
5
|
* Converts plain usernames (e.g., "tom") to email format (e.g., "tom@hellm.ai")
|
|
6
6
|
* using domain from git config or .lumenflow.config.yaml.
|
|
7
|
+
*
|
|
8
|
+
* WU-1068: Removed hardcoded patientpath.co.uk domain. Domain is now inferred
|
|
9
|
+
* from git config user.email or .lumenflow.config.yaml OWNER_EMAIL.
|
|
7
10
|
*/
|
|
8
11
|
/**
|
|
9
12
|
* Default domain fallback when git config and lumenflow config unavailable
|
|
13
|
+
* WU-1068: Changed from hardcoded 'patientpath.co.uk' to generic default
|
|
10
14
|
*/
|
|
11
|
-
export declare const DEFAULT_DOMAIN
|
|
15
|
+
export declare const DEFAULT_DOMAIN: string;
|
|
12
16
|
/**
|
|
13
17
|
* Check if a value is a valid email address (simple check)
|
|
14
18
|
*
|
package/dist/user-normalizer.js
CHANGED
|
@@ -4,14 +4,19 @@
|
|
|
4
4
|
* Provides email normalization and domain inference for WU ownership.
|
|
5
5
|
* Converts plain usernames (e.g., "tom") to email format (e.g., "tom@hellm.ai")
|
|
6
6
|
* using domain from git config or .lumenflow.config.yaml.
|
|
7
|
+
*
|
|
8
|
+
* WU-1068: Removed hardcoded patientpath.co.uk domain. Domain is now inferred
|
|
9
|
+
* from git config user.email or .lumenflow.config.yaml OWNER_EMAIL.
|
|
7
10
|
*/
|
|
8
11
|
import { readFile, access } from 'node:fs/promises';
|
|
9
12
|
import { join } from 'node:path';
|
|
10
13
|
import { getGitForCwd } from './git-adapter.js';
|
|
14
|
+
import { DEFAULTS } from './wu-constants.js';
|
|
11
15
|
/**
|
|
12
16
|
* Default domain fallback when git config and lumenflow config unavailable
|
|
17
|
+
* WU-1068: Changed from hardcoded 'patientpath.co.uk' to generic default
|
|
13
18
|
*/
|
|
14
|
-
export const DEFAULT_DOMAIN =
|
|
19
|
+
export const DEFAULT_DOMAIN = DEFAULTS.EMAIL_DOMAIN;
|
|
15
20
|
/**
|
|
16
21
|
* Minimum length for a valid email local part
|
|
17
22
|
*/
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
import nhsValidator from 'nhs-number-validator';
|
|
14
14
|
import { isValid as isValidPostcode, parse as parsePostcode } from 'postcode';
|
|
15
15
|
import { PHI_TYPES, MEDICAL_CONTEXT_KEYWORDS, MEDICAL_CONTEXT_WINDOW_SIZE, TEST_NHS_NUMBERS, NHS_TEST_PREFIX, TEST_POSTCODES, TEST_DATA_MARKERS, EXCLUDED_PATH_PATTERNS, NHS_CANDIDATE_PATTERN, } from './phi-constants.js';
|
|
16
|
+
import { PHI_CONFIG } from '../wu-constants.js';
|
|
16
17
|
/**
|
|
17
18
|
* Check if a file path should be excluded from PHI scanning
|
|
18
19
|
*
|
|
@@ -137,6 +138,11 @@ export function scanForPHI(content, options = {}) {
|
|
|
137
138
|
matches: [],
|
|
138
139
|
warnings: [],
|
|
139
140
|
};
|
|
141
|
+
// WU-1068: PHI scanning is gated behind config flag
|
|
142
|
+
// Projects must explicitly opt-in via LUMENFLOW_PHI_ENABLED=1 or config
|
|
143
|
+
if (!PHI_CONFIG.ENABLED) {
|
|
144
|
+
return result;
|
|
145
|
+
}
|
|
140
146
|
// Handle null/undefined/empty content
|
|
141
147
|
if (!content || typeof content !== 'string' || content.trim() === '') {
|
|
142
148
|
return result;
|
|
@@ -18,6 +18,10 @@
|
|
|
18
18
|
* pnpm monorepos create node_modules in each package with symlinks
|
|
19
19
|
* to the .pnpm store. turbo typecheck and tests need these to resolve imports.
|
|
20
20
|
*
|
|
21
|
+
* WU-1068: Removed @patientpath references. Only @lumenflow packages are
|
|
22
|
+
* relevant to the LumenFlow framework. Project-specific paths should be
|
|
23
|
+
* configured in .lumenflow.config.yaml.
|
|
24
|
+
*
|
|
21
25
|
* @type {string[]}
|
|
22
26
|
*/
|
|
23
27
|
export declare const NESTED_PACKAGE_PATHS: string[];
|
package/dist/worktree-symlink.js
CHANGED
|
@@ -43,30 +43,24 @@ const PNPM_DIR = '.pnpm';
|
|
|
43
43
|
* pnpm monorepos create node_modules in each package with symlinks
|
|
44
44
|
* to the .pnpm store. turbo typecheck and tests need these to resolve imports.
|
|
45
45
|
*
|
|
46
|
+
* WU-1068: Removed @patientpath references. Only @lumenflow packages are
|
|
47
|
+
* relevant to the LumenFlow framework. Project-specific paths should be
|
|
48
|
+
* configured in .lumenflow.config.yaml.
|
|
49
|
+
*
|
|
46
50
|
* @type {string[]}
|
|
47
51
|
*/
|
|
48
52
|
export const NESTED_PACKAGE_PATHS = [
|
|
49
|
-
// Packages -
|
|
50
|
-
'packages/
|
|
51
|
-
|
|
52
|
-
'packages/@
|
|
53
|
-
'packages/@
|
|
54
|
-
'packages/@
|
|
55
|
-
'packages/@
|
|
56
|
-
'packages/@
|
|
57
|
-
//
|
|
58
|
-
'packages/@lumenflow/api',
|
|
59
|
-
'packages/@lumenflow/application',
|
|
60
|
-
'packages/@lumenflow/infrastructure',
|
|
61
|
-
// Packages - lumenflow-*
|
|
62
|
-
'packages/lumenflow-cli',
|
|
63
|
-
'packages/lumenflow-tools',
|
|
64
|
-
// Packages - beacon-explainer (WU-2427: added for typecheck resolution)
|
|
65
|
-
'packages/beacon-explainer',
|
|
66
|
-
// Apps
|
|
53
|
+
// Packages - @lumenflow/*
|
|
54
|
+
'packages/@lumenflow/core',
|
|
55
|
+
'packages/@lumenflow/cli',
|
|
56
|
+
'packages/@lumenflow/memory',
|
|
57
|
+
'packages/@lumenflow/agent',
|
|
58
|
+
'packages/@lumenflow/metrics',
|
|
59
|
+
'packages/@lumenflow/initiatives',
|
|
60
|
+
'packages/@lumenflow/shims',
|
|
61
|
+
// Apps (generic placeholders)
|
|
67
62
|
'apps/web',
|
|
68
|
-
'apps/
|
|
69
|
-
'apps/hellm-ai', // WU-2427: added for typecheck resolution
|
|
63
|
+
'apps/docs',
|
|
70
64
|
];
|
|
71
65
|
/**
|
|
72
66
|
* Check if a symlink target points into a worktrees directory
|
|
@@ -30,6 +30,7 @@ export declare function checkWUConsistency(id: any, projectRoot?: string): Promi
|
|
|
30
30
|
backlogInProgress?: undefined;
|
|
31
31
|
statusInProgress?: undefined;
|
|
32
32
|
hasWorktree?: undefined;
|
|
33
|
+
worktreePathExists?: undefined;
|
|
33
34
|
};
|
|
34
35
|
} | {
|
|
35
36
|
valid: boolean;
|
|
@@ -41,6 +42,7 @@ export declare function checkWUConsistency(id: any, projectRoot?: string): Promi
|
|
|
41
42
|
backlogInProgress: boolean;
|
|
42
43
|
statusInProgress: boolean;
|
|
43
44
|
hasWorktree: boolean;
|
|
45
|
+
worktreePathExists: boolean;
|
|
44
46
|
wuExists?: undefined;
|
|
45
47
|
};
|
|
46
48
|
}>;
|
|
@@ -17,7 +17,7 @@ import { constants } from 'node:fs';
|
|
|
17
17
|
import path from 'node:path';
|
|
18
18
|
import { parseYAML, stringifyYAML } from './wu-yaml.js';
|
|
19
19
|
import { WU_PATHS } from './wu-paths.js';
|
|
20
|
-
import { CONSISTENCY_TYPES, LOG_PREFIX, REMOTES, STRING_LITERALS, toKebab, WU_STATUS, YAML_OPTIONS, } from './wu-constants.js';
|
|
20
|
+
import { CONSISTENCY_TYPES, CONSISTENCY_MESSAGES, LOG_PREFIX, REMOTES, STRING_LITERALS, toKebab, WU_STATUS, YAML_OPTIONS, } from './wu-constants.js';
|
|
21
21
|
import { todayISO } from './date-utils.js';
|
|
22
22
|
import { createGitForPath } from './git-adapter.js';
|
|
23
23
|
/**
|
|
@@ -45,6 +45,7 @@ export async function checkWUConsistency(id, projectRoot = process.cwd()) {
|
|
|
45
45
|
const yamlStatus = wuDoc?.status || 'unknown';
|
|
46
46
|
const lane = wuDoc?.lane || '';
|
|
47
47
|
const title = wuDoc?.title || '';
|
|
48
|
+
const worktreePathFromYaml = wuDoc?.worktree_path || '';
|
|
48
49
|
// Check stamp existence
|
|
49
50
|
let hasStamp = false;
|
|
50
51
|
try {
|
|
@@ -74,6 +75,7 @@ export async function checkWUConsistency(id, projectRoot = process.cwd()) {
|
|
|
74
75
|
const { inProgress: statusInProgress } = parseStatusSections(statusContent, id);
|
|
75
76
|
// Check for worktree
|
|
76
77
|
const hasWorktree = await checkWorktreeExists(id, projectRoot);
|
|
78
|
+
const worktreePathExists = await checkWorktreePathExists(worktreePathFromYaml);
|
|
77
79
|
// Detection logic
|
|
78
80
|
// 1. YAML done but in status.md In Progress
|
|
79
81
|
if (yamlStatus === WU_STATUS.DONE && statusInProgress) {
|
|
@@ -129,6 +131,19 @@ export async function checkWUConsistency(id, projectRoot = process.cwd()) {
|
|
|
129
131
|
canAutoRepair: true,
|
|
130
132
|
});
|
|
131
133
|
}
|
|
134
|
+
// 6. Claimed WU missing worktree directory
|
|
135
|
+
if (worktreePathFromYaml &&
|
|
136
|
+
!worktreePathExists &&
|
|
137
|
+
(yamlStatus === WU_STATUS.IN_PROGRESS || yamlStatus === WU_STATUS.BLOCKED)) {
|
|
138
|
+
errors.push({
|
|
139
|
+
type: CONSISTENCY_TYPES.MISSING_WORKTREE_CLAIMED,
|
|
140
|
+
wuId: id,
|
|
141
|
+
title,
|
|
142
|
+
description: CONSISTENCY_MESSAGES.MISSING_WORKTREE_CLAIMED(id, yamlStatus, worktreePathFromYaml),
|
|
143
|
+
repairAction: CONSISTENCY_MESSAGES.MISSING_WORKTREE_CLAIMED_REPAIR,
|
|
144
|
+
canAutoRepair: false,
|
|
145
|
+
});
|
|
146
|
+
}
|
|
132
147
|
return {
|
|
133
148
|
valid: errors.length === 0,
|
|
134
149
|
errors,
|
|
@@ -139,6 +154,7 @@ export async function checkWUConsistency(id, projectRoot = process.cwd()) {
|
|
|
139
154
|
backlogInProgress,
|
|
140
155
|
statusInProgress,
|
|
141
156
|
hasWorktree,
|
|
157
|
+
worktreePathExists,
|
|
142
158
|
},
|
|
143
159
|
};
|
|
144
160
|
}
|
|
@@ -565,3 +581,21 @@ async function checkWorktreeExists(id, projectRoot) {
|
|
|
565
581
|
return false;
|
|
566
582
|
}
|
|
567
583
|
}
|
|
584
|
+
/**
|
|
585
|
+
* Check whether a worktree path exists on disk
|
|
586
|
+
*
|
|
587
|
+
* @param {string} worktreePath - Worktree path from WU YAML
|
|
588
|
+
* @returns {Promise<boolean>} True if path exists
|
|
589
|
+
*/
|
|
590
|
+
async function checkWorktreePathExists(worktreePath) {
|
|
591
|
+
if (!worktreePath) {
|
|
592
|
+
return false;
|
|
593
|
+
}
|
|
594
|
+
try {
|
|
595
|
+
await access(worktreePath, constants.R_OK);
|
|
596
|
+
return true;
|
|
597
|
+
}
|
|
598
|
+
catch {
|
|
599
|
+
return false;
|
|
600
|
+
}
|
|
601
|
+
}
|