@lumenflow/core 2.5.1 → 2.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/gates-config.d.ts +72 -0
- package/dist/gates-config.js +190 -0
- package/dist/lumenflow-config-schema.d.ts +115 -0
- package/dist/lumenflow-config-schema.js +128 -0
- package/dist/wu-constants.d.ts +69 -0
- package/dist/wu-constants.js +78 -0
- package/package.json +2 -2
package/dist/gates-config.d.ts
CHANGED
|
@@ -204,3 +204,75 @@ export interface TestPolicy extends CoverageConfig {
|
|
|
204
204
|
* @returns Resolved test policy including tests_required
|
|
205
205
|
*/
|
|
206
206
|
export declare function resolveTestPolicy(projectRoot: string): TestPolicy;
|
|
207
|
+
/**
|
|
208
|
+
* WU-1356: Supported package managers type
|
|
209
|
+
* Re-exported from lumenflow-config-schema to avoid circular import
|
|
210
|
+
*/
|
|
211
|
+
type PackageManager = 'pnpm' | 'npm' | 'yarn' | 'bun';
|
|
212
|
+
/**
|
|
213
|
+
* WU-1356: Supported test runners type
|
|
214
|
+
* Re-exported from lumenflow-config-schema to avoid circular import
|
|
215
|
+
*/
|
|
216
|
+
type TestRunner = 'vitest' | 'jest' | 'mocha';
|
|
217
|
+
/**
|
|
218
|
+
* WU-1356: Gates commands configuration type
|
|
219
|
+
*/
|
|
220
|
+
export interface GatesCommands {
|
|
221
|
+
test_full: string;
|
|
222
|
+
test_docs_only: string;
|
|
223
|
+
test_incremental: string;
|
|
224
|
+
lint?: string;
|
|
225
|
+
typecheck?: string;
|
|
226
|
+
format?: string;
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* WU-1356: Resolve package manager from configuration
|
|
230
|
+
*
|
|
231
|
+
* Reads the package_manager field from .lumenflow.config.yaml.
|
|
232
|
+
* Returns 'pnpm' as default if not configured.
|
|
233
|
+
*
|
|
234
|
+
* @param projectRoot - Project root directory
|
|
235
|
+
* @returns Resolved package manager ('pnpm', 'npm', 'yarn', or 'bun')
|
|
236
|
+
*/
|
|
237
|
+
export declare function resolvePackageManager(projectRoot: string): PackageManager;
|
|
238
|
+
/**
|
|
239
|
+
* WU-1356: Resolve test runner from configuration
|
|
240
|
+
*
|
|
241
|
+
* Reads the test_runner field from .lumenflow.config.yaml.
|
|
242
|
+
* Returns 'vitest' as default if not configured.
|
|
243
|
+
*
|
|
244
|
+
* @param projectRoot - Project root directory
|
|
245
|
+
* @returns Resolved test runner ('vitest', 'jest', or 'mocha')
|
|
246
|
+
*/
|
|
247
|
+
export declare function resolveTestRunner(projectRoot: string): TestRunner;
|
|
248
|
+
/**
|
|
249
|
+
* WU-1356: Resolve build command from configuration
|
|
250
|
+
*
|
|
251
|
+
* Reads the build_command field from .lumenflow.config.yaml.
|
|
252
|
+
* If not configured, uses default based on package_manager.
|
|
253
|
+
*
|
|
254
|
+
* @param projectRoot - Project root directory
|
|
255
|
+
* @returns Resolved build command
|
|
256
|
+
*/
|
|
257
|
+
export declare function resolveBuildCommand(projectRoot: string): string;
|
|
258
|
+
/**
|
|
259
|
+
* WU-1356: Resolve gates commands from configuration
|
|
260
|
+
*
|
|
261
|
+
* Reads gates.commands from .lumenflow.config.yaml.
|
|
262
|
+
* Merges with defaults based on package_manager if not fully specified.
|
|
263
|
+
*
|
|
264
|
+
* @param projectRoot - Project root directory
|
|
265
|
+
* @returns Resolved gates commands configuration
|
|
266
|
+
*/
|
|
267
|
+
export declare function resolveGatesCommands(projectRoot: string): GatesCommands;
|
|
268
|
+
/**
|
|
269
|
+
* WU-1356: Get ignore patterns for test runner
|
|
270
|
+
*
|
|
271
|
+
* Returns patterns to ignore when detecting changed tests,
|
|
272
|
+
* based on the test runner configuration.
|
|
273
|
+
*
|
|
274
|
+
* @param testRunner - Test runner type (vitest, jest, mocha)
|
|
275
|
+
* @returns Array of ignore patterns
|
|
276
|
+
*/
|
|
277
|
+
export declare function getIgnorePatterns(testRunner: TestRunner): string[];
|
|
278
|
+
export {};
|
package/dist/gates-config.js
CHANGED
|
@@ -453,3 +453,193 @@ export function resolveTestPolicy(projectRoot) {
|
|
|
453
453
|
tests_required: policy.tests_required,
|
|
454
454
|
};
|
|
455
455
|
}
|
|
456
|
+
/**
|
|
457
|
+
* WU-1356: Default gates commands by package manager
|
|
458
|
+
*
|
|
459
|
+
* Provides sensible defaults for different package manager and test runner combinations.
|
|
460
|
+
*/
|
|
461
|
+
const DEFAULT_GATES_COMMANDS = {
|
|
462
|
+
pnpm: {
|
|
463
|
+
test_full: 'pnpm turbo run test',
|
|
464
|
+
test_docs_only: '',
|
|
465
|
+
test_incremental: 'pnpm vitest run --changed origin/main',
|
|
466
|
+
lint: 'pnpm lint',
|
|
467
|
+
typecheck: 'pnpm typecheck',
|
|
468
|
+
format: 'pnpm format:check',
|
|
469
|
+
},
|
|
470
|
+
npm: {
|
|
471
|
+
test_full: 'npm test',
|
|
472
|
+
test_docs_only: '',
|
|
473
|
+
test_incremental: 'npm test -- --onlyChanged',
|
|
474
|
+
lint: 'npm run lint',
|
|
475
|
+
typecheck: 'npm run typecheck',
|
|
476
|
+
format: 'npm run format:check',
|
|
477
|
+
},
|
|
478
|
+
yarn: {
|
|
479
|
+
test_full: 'yarn test',
|
|
480
|
+
test_docs_only: '',
|
|
481
|
+
test_incremental: 'yarn test --onlyChanged',
|
|
482
|
+
lint: 'yarn lint',
|
|
483
|
+
typecheck: 'yarn typecheck',
|
|
484
|
+
format: 'yarn format:check',
|
|
485
|
+
},
|
|
486
|
+
bun: {
|
|
487
|
+
test_full: 'bun test',
|
|
488
|
+
test_docs_only: '',
|
|
489
|
+
test_incremental: 'bun test --changed',
|
|
490
|
+
lint: 'bun run lint',
|
|
491
|
+
typecheck: 'bun run typecheck',
|
|
492
|
+
format: 'bun run format:check',
|
|
493
|
+
},
|
|
494
|
+
};
|
|
495
|
+
/**
|
|
496
|
+
* WU-1356: Default build commands by package manager
|
|
497
|
+
*/
|
|
498
|
+
const DEFAULT_BUILD_COMMANDS = {
|
|
499
|
+
pnpm: 'pnpm --filter @lumenflow/cli build',
|
|
500
|
+
npm: 'npm run build --workspace @lumenflow/cli',
|
|
501
|
+
yarn: 'yarn workspace @lumenflow/cli build',
|
|
502
|
+
bun: 'bun run --filter @lumenflow/cli build',
|
|
503
|
+
};
|
|
504
|
+
/**
|
|
505
|
+
* WU-1356: Ignore patterns by test runner
|
|
506
|
+
*
|
|
507
|
+
* Different test runners use different cache directories that should be ignored.
|
|
508
|
+
*/
|
|
509
|
+
const IGNORE_PATTERNS_BY_RUNNER = {
|
|
510
|
+
vitest: ['.turbo'],
|
|
511
|
+
jest: ['coverage', '.jest-cache'],
|
|
512
|
+
mocha: ['coverage', '.nyc_output'],
|
|
513
|
+
};
|
|
514
|
+
/**
|
|
515
|
+
* WU-1356: Resolve package manager from configuration
|
|
516
|
+
*
|
|
517
|
+
* Reads the package_manager field from .lumenflow.config.yaml.
|
|
518
|
+
* Returns 'pnpm' as default if not configured.
|
|
519
|
+
*
|
|
520
|
+
* @param projectRoot - Project root directory
|
|
521
|
+
* @returns Resolved package manager ('pnpm', 'npm', 'yarn', or 'bun')
|
|
522
|
+
*/
|
|
523
|
+
export function resolvePackageManager(projectRoot) {
|
|
524
|
+
const configPath = path.join(projectRoot, CONFIG_FILE_NAME);
|
|
525
|
+
if (!fs.existsSync(configPath)) {
|
|
526
|
+
return 'pnpm';
|
|
527
|
+
}
|
|
528
|
+
try {
|
|
529
|
+
const content = fs.readFileSync(configPath, 'utf8');
|
|
530
|
+
const data = yaml.parse(content);
|
|
531
|
+
const pm = data?.package_manager;
|
|
532
|
+
if (pm && ['pnpm', 'npm', 'yarn', 'bun'].includes(pm)) {
|
|
533
|
+
return pm;
|
|
534
|
+
}
|
|
535
|
+
return 'pnpm';
|
|
536
|
+
}
|
|
537
|
+
catch {
|
|
538
|
+
return 'pnpm';
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
/**
|
|
542
|
+
* WU-1356: Resolve test runner from configuration
|
|
543
|
+
*
|
|
544
|
+
* Reads the test_runner field from .lumenflow.config.yaml.
|
|
545
|
+
* Returns 'vitest' as default if not configured.
|
|
546
|
+
*
|
|
547
|
+
* @param projectRoot - Project root directory
|
|
548
|
+
* @returns Resolved test runner ('vitest', 'jest', or 'mocha')
|
|
549
|
+
*/
|
|
550
|
+
export function resolveTestRunner(projectRoot) {
|
|
551
|
+
const configPath = path.join(projectRoot, CONFIG_FILE_NAME);
|
|
552
|
+
if (!fs.existsSync(configPath)) {
|
|
553
|
+
return 'vitest';
|
|
554
|
+
}
|
|
555
|
+
try {
|
|
556
|
+
const content = fs.readFileSync(configPath, 'utf8');
|
|
557
|
+
const data = yaml.parse(content);
|
|
558
|
+
const runner = data?.test_runner;
|
|
559
|
+
if (runner && ['vitest', 'jest', 'mocha'].includes(runner)) {
|
|
560
|
+
return runner;
|
|
561
|
+
}
|
|
562
|
+
return 'vitest';
|
|
563
|
+
}
|
|
564
|
+
catch {
|
|
565
|
+
return 'vitest';
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
/**
|
|
569
|
+
* WU-1356: Resolve build command from configuration
|
|
570
|
+
*
|
|
571
|
+
* Reads the build_command field from .lumenflow.config.yaml.
|
|
572
|
+
* If not configured, uses default based on package_manager.
|
|
573
|
+
*
|
|
574
|
+
* @param projectRoot - Project root directory
|
|
575
|
+
* @returns Resolved build command
|
|
576
|
+
*/
|
|
577
|
+
export function resolveBuildCommand(projectRoot) {
|
|
578
|
+
const configPath = path.join(projectRoot, CONFIG_FILE_NAME);
|
|
579
|
+
const defaultPm = resolvePackageManager(projectRoot);
|
|
580
|
+
if (!fs.existsSync(configPath)) {
|
|
581
|
+
return DEFAULT_BUILD_COMMANDS[defaultPm];
|
|
582
|
+
}
|
|
583
|
+
try {
|
|
584
|
+
const content = fs.readFileSync(configPath, 'utf8');
|
|
585
|
+
const data = yaml.parse(content);
|
|
586
|
+
// If explicit build_command is set, use it
|
|
587
|
+
if (data?.build_command && typeof data.build_command === 'string') {
|
|
588
|
+
return data.build_command;
|
|
589
|
+
}
|
|
590
|
+
// Otherwise, use default for the configured package manager
|
|
591
|
+
return DEFAULT_BUILD_COMMANDS[defaultPm];
|
|
592
|
+
}
|
|
593
|
+
catch {
|
|
594
|
+
return DEFAULT_BUILD_COMMANDS[defaultPm];
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
/**
|
|
598
|
+
* WU-1356: Resolve gates commands from configuration
|
|
599
|
+
*
|
|
600
|
+
* Reads gates.commands from .lumenflow.config.yaml.
|
|
601
|
+
* Merges with defaults based on package_manager if not fully specified.
|
|
602
|
+
*
|
|
603
|
+
* @param projectRoot - Project root directory
|
|
604
|
+
* @returns Resolved gates commands configuration
|
|
605
|
+
*/
|
|
606
|
+
export function resolveGatesCommands(projectRoot) {
|
|
607
|
+
const configPath = path.join(projectRoot, CONFIG_FILE_NAME);
|
|
608
|
+
const pm = resolvePackageManager(projectRoot);
|
|
609
|
+
const defaults = DEFAULT_GATES_COMMANDS[pm];
|
|
610
|
+
if (!fs.existsSync(configPath)) {
|
|
611
|
+
return defaults;
|
|
612
|
+
}
|
|
613
|
+
try {
|
|
614
|
+
const content = fs.readFileSync(configPath, 'utf8');
|
|
615
|
+
const data = yaml.parse(content);
|
|
616
|
+
const commands = data?.gates?.commands;
|
|
617
|
+
if (!commands) {
|
|
618
|
+
return defaults;
|
|
619
|
+
}
|
|
620
|
+
// Merge user config with defaults (user config wins)
|
|
621
|
+
return {
|
|
622
|
+
test_full: commands.test_full ?? defaults.test_full,
|
|
623
|
+
test_docs_only: commands.test_docs_only ?? defaults.test_docs_only,
|
|
624
|
+
test_incremental: commands.test_incremental ?? defaults.test_incremental,
|
|
625
|
+
lint: commands.lint ?? defaults.lint,
|
|
626
|
+
typecheck: commands.typecheck ?? defaults.typecheck,
|
|
627
|
+
format: commands.format ?? defaults.format,
|
|
628
|
+
};
|
|
629
|
+
}
|
|
630
|
+
catch {
|
|
631
|
+
return defaults;
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
/**
|
|
635
|
+
* WU-1356: Get ignore patterns for test runner
|
|
636
|
+
*
|
|
637
|
+
* Returns patterns to ignore when detecting changed tests,
|
|
638
|
+
* based on the test runner configuration.
|
|
639
|
+
*
|
|
640
|
+
* @param testRunner - Test runner type (vitest, jest, mocha)
|
|
641
|
+
* @returns Array of ignore patterns
|
|
642
|
+
*/
|
|
643
|
+
export function getIgnorePatterns(testRunner) {
|
|
644
|
+
return IGNORE_PATTERNS_BY_RUNNER[testRunner] ?? ['.turbo'];
|
|
645
|
+
}
|
|
@@ -7,6 +7,68 @@
|
|
|
7
7
|
* @module lumenflow-config-schema
|
|
8
8
|
*/
|
|
9
9
|
import { z } from 'zod';
|
|
10
|
+
/**
|
|
11
|
+
* WU-1356: Package manager options
|
|
12
|
+
*
|
|
13
|
+
* Supported package managers for LumenFlow CLI operations.
|
|
14
|
+
* Used for build commands, dependency installation, and script execution.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```yaml
|
|
18
|
+
* package_manager: npm
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export declare const PackageManagerSchema: z.ZodDefault<z.ZodEnum<{
|
|
22
|
+
pnpm: "pnpm";
|
|
23
|
+
npm: "npm";
|
|
24
|
+
yarn: "yarn";
|
|
25
|
+
bun: "bun";
|
|
26
|
+
}>>;
|
|
27
|
+
/** WU-1356: TypeScript type for package manager */
|
|
28
|
+
export type PackageManager = z.infer<typeof PackageManagerSchema>;
|
|
29
|
+
/**
|
|
30
|
+
* WU-1356: Test runner options
|
|
31
|
+
*
|
|
32
|
+
* Supported test runners for incremental test detection and execution.
|
|
33
|
+
* Determines how changed tests are detected and ignore patterns are derived.
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```yaml
|
|
37
|
+
* test_runner: jest
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
export declare const TestRunnerSchema: z.ZodDefault<z.ZodEnum<{
|
|
41
|
+
vitest: "vitest";
|
|
42
|
+
jest: "jest";
|
|
43
|
+
mocha: "mocha";
|
|
44
|
+
}>>;
|
|
45
|
+
/** WU-1356: TypeScript type for test runner */
|
|
46
|
+
export type TestRunner = z.infer<typeof TestRunnerSchema>;
|
|
47
|
+
/**
|
|
48
|
+
* WU-1356: Gates commands configuration
|
|
49
|
+
*
|
|
50
|
+
* Configurable test commands for gates execution.
|
|
51
|
+
* Replaces hard-coded turbo/vitest commands with user-configurable alternatives.
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```yaml
|
|
55
|
+
* gates:
|
|
56
|
+
* commands:
|
|
57
|
+
* test_full: 'npm test'
|
|
58
|
+
* test_docs_only: 'npm test -- --testPathPattern=docs'
|
|
59
|
+
* test_incremental: 'npm test -- --onlyChanged'
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
export declare const GatesCommandsConfigSchema: z.ZodObject<{
|
|
63
|
+
test_full: z.ZodDefault<z.ZodString>;
|
|
64
|
+
test_docs_only: z.ZodDefault<z.ZodString>;
|
|
65
|
+
test_incremental: z.ZodDefault<z.ZodString>;
|
|
66
|
+
lint: z.ZodOptional<z.ZodString>;
|
|
67
|
+
typecheck: z.ZodOptional<z.ZodString>;
|
|
68
|
+
format: z.ZodOptional<z.ZodString>;
|
|
69
|
+
}, z.core.$strip>;
|
|
70
|
+
/** WU-1356: TypeScript type for gates commands config */
|
|
71
|
+
export type GatesCommandsConfig = z.infer<typeof GatesCommandsConfigSchema>;
|
|
10
72
|
/**
|
|
11
73
|
* WU-1325: Lock policy for lane-level WIP enforcement
|
|
12
74
|
*
|
|
@@ -172,6 +234,20 @@ export declare const GatesConfigSchema: z.ZodObject<{
|
|
|
172
234
|
threshold: z.ZodOptional<z.ZodNumber>;
|
|
173
235
|
}, z.core.$strip>]>>;
|
|
174
236
|
}, z.core.$strip>>;
|
|
237
|
+
commands: z.ZodDefault<z.ZodObject<{
|
|
238
|
+
test_full: z.ZodDefault<z.ZodString>;
|
|
239
|
+
test_docs_only: z.ZodDefault<z.ZodString>;
|
|
240
|
+
test_incremental: z.ZodDefault<z.ZodString>;
|
|
241
|
+
lint: z.ZodOptional<z.ZodString>;
|
|
242
|
+
typecheck: z.ZodOptional<z.ZodString>;
|
|
243
|
+
format: z.ZodOptional<z.ZodString>;
|
|
244
|
+
}, z.core.$strip>>;
|
|
245
|
+
ignore_patterns: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
246
|
+
lane_health: z.ZodDefault<z.ZodEnum<{
|
|
247
|
+
error: "error";
|
|
248
|
+
off: "off";
|
|
249
|
+
warn: "warn";
|
|
250
|
+
}>>;
|
|
175
251
|
}, z.core.$strip>;
|
|
176
252
|
/**
|
|
177
253
|
* WU-1203: Progress signals configuration for sub-agent coordination
|
|
@@ -550,6 +626,20 @@ export declare const LumenFlowConfigSchema: z.ZodObject<{
|
|
|
550
626
|
threshold: z.ZodOptional<z.ZodNumber>;
|
|
551
627
|
}, z.core.$strip>]>>;
|
|
552
628
|
}, z.core.$strip>>;
|
|
629
|
+
commands: z.ZodDefault<z.ZodObject<{
|
|
630
|
+
test_full: z.ZodDefault<z.ZodString>;
|
|
631
|
+
test_docs_only: z.ZodDefault<z.ZodString>;
|
|
632
|
+
test_incremental: z.ZodDefault<z.ZodString>;
|
|
633
|
+
lint: z.ZodOptional<z.ZodString>;
|
|
634
|
+
typecheck: z.ZodOptional<z.ZodString>;
|
|
635
|
+
format: z.ZodOptional<z.ZodString>;
|
|
636
|
+
}, z.core.$strip>>;
|
|
637
|
+
ignore_patterns: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
638
|
+
lane_health: z.ZodDefault<z.ZodEnum<{
|
|
639
|
+
error: "error";
|
|
640
|
+
off: "off";
|
|
641
|
+
warn: "warn";
|
|
642
|
+
}>>;
|
|
553
643
|
}, z.core.$strip>>;
|
|
554
644
|
memory: z.ZodDefault<z.ZodObject<{
|
|
555
645
|
directory: z.ZodDefault<z.ZodString>;
|
|
@@ -679,6 +769,18 @@ export declare const LumenFlowConfigSchema: z.ZodObject<{
|
|
|
679
769
|
code_paths: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
680
770
|
}, z.core.$strip>>>;
|
|
681
771
|
}, z.core.$strip>>;
|
|
772
|
+
package_manager: z.ZodDefault<z.ZodEnum<{
|
|
773
|
+
pnpm: "pnpm";
|
|
774
|
+
npm: "npm";
|
|
775
|
+
yarn: "yarn";
|
|
776
|
+
bun: "bun";
|
|
777
|
+
}>>;
|
|
778
|
+
test_runner: z.ZodDefault<z.ZodEnum<{
|
|
779
|
+
vitest: "vitest";
|
|
780
|
+
jest: "jest";
|
|
781
|
+
mocha: "mocha";
|
|
782
|
+
}>>;
|
|
783
|
+
build_command: z.ZodDefault<z.ZodString>;
|
|
682
784
|
}, z.core.$strip>;
|
|
683
785
|
/**
|
|
684
786
|
* TypeScript types inferred from schemas
|
|
@@ -787,6 +889,15 @@ export declare function validateConfig(data: unknown): z.ZodSafeParseResult<{
|
|
|
787
889
|
minCoverage: number;
|
|
788
890
|
enableSafetyCriticalTests: boolean;
|
|
789
891
|
enableInvariants: boolean;
|
|
892
|
+
commands: {
|
|
893
|
+
test_full: string;
|
|
894
|
+
test_docs_only: string;
|
|
895
|
+
test_incremental: string;
|
|
896
|
+
lint?: string;
|
|
897
|
+
typecheck?: string;
|
|
898
|
+
format?: string;
|
|
899
|
+
};
|
|
900
|
+
lane_health: "error" | "off" | "warn";
|
|
790
901
|
execution?: {
|
|
791
902
|
preset?: string;
|
|
792
903
|
setup?: string | {
|
|
@@ -819,6 +930,7 @@ export declare function validateConfig(data: unknown): z.ZodSafeParseResult<{
|
|
|
819
930
|
threshold?: number;
|
|
820
931
|
};
|
|
821
932
|
};
|
|
933
|
+
ignore_patterns?: string[];
|
|
822
934
|
};
|
|
823
935
|
memory: {
|
|
824
936
|
directory: string;
|
|
@@ -882,6 +994,9 @@ export declare function validateConfig(data: unknown): z.ZodSafeParseResult<{
|
|
|
882
994
|
enabled: boolean;
|
|
883
995
|
};
|
|
884
996
|
};
|
|
997
|
+
package_manager: "pnpm" | "npm" | "yarn" | "bun";
|
|
998
|
+
test_runner: "vitest" | "jest" | "mocha";
|
|
999
|
+
build_command: string;
|
|
885
1000
|
methodology?: {
|
|
886
1001
|
testing: "tdd" | "test-after" | "none";
|
|
887
1002
|
architecture: "none" | "hexagonal" | "layered";
|
|
@@ -11,6 +11,77 @@ import { z } from 'zod';
|
|
|
11
11
|
import { GatesExecutionConfigSchema } from './gates-config.js';
|
|
12
12
|
// WU-1259: Import methodology config schema for resolvePolicy()
|
|
13
13
|
import { MethodologyConfigSchema } from './resolve-policy.js';
|
|
14
|
+
/**
|
|
15
|
+
* WU-1356: Package manager options
|
|
16
|
+
*
|
|
17
|
+
* Supported package managers for LumenFlow CLI operations.
|
|
18
|
+
* Used for build commands, dependency installation, and script execution.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```yaml
|
|
22
|
+
* package_manager: npm
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export const PackageManagerSchema = z.enum(['pnpm', 'npm', 'yarn', 'bun']).default('pnpm');
|
|
26
|
+
/**
|
|
27
|
+
* WU-1356: Test runner options
|
|
28
|
+
*
|
|
29
|
+
* Supported test runners for incremental test detection and execution.
|
|
30
|
+
* Determines how changed tests are detected and ignore patterns are derived.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```yaml
|
|
34
|
+
* test_runner: jest
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
export const TestRunnerSchema = z.enum(['vitest', 'jest', 'mocha']).default('vitest');
|
|
38
|
+
/**
|
|
39
|
+
* WU-1356: Gates commands configuration
|
|
40
|
+
*
|
|
41
|
+
* Configurable test commands for gates execution.
|
|
42
|
+
* Replaces hard-coded turbo/vitest commands with user-configurable alternatives.
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```yaml
|
|
46
|
+
* gates:
|
|
47
|
+
* commands:
|
|
48
|
+
* test_full: 'npm test'
|
|
49
|
+
* test_docs_only: 'npm test -- --testPathPattern=docs'
|
|
50
|
+
* test_incremental: 'npm test -- --onlyChanged'
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
53
|
+
export const GatesCommandsConfigSchema = z.object({
|
|
54
|
+
/**
|
|
55
|
+
* Command to run full test suite.
|
|
56
|
+
* Default: 'pnpm turbo run test'
|
|
57
|
+
*/
|
|
58
|
+
test_full: z.string().default('pnpm turbo run test'),
|
|
59
|
+
/**
|
|
60
|
+
* Command to run tests in docs-only mode.
|
|
61
|
+
* Default: empty (skip tests in docs-only mode)
|
|
62
|
+
*/
|
|
63
|
+
test_docs_only: z.string().default(''),
|
|
64
|
+
/**
|
|
65
|
+
* Command to run incremental tests (changed files only).
|
|
66
|
+
* Default: 'pnpm vitest run --changed origin/main'
|
|
67
|
+
*/
|
|
68
|
+
test_incremental: z.string().default('pnpm vitest run --changed origin/main'),
|
|
69
|
+
/**
|
|
70
|
+
* Command to run lint checks.
|
|
71
|
+
* Default: 'pnpm lint'
|
|
72
|
+
*/
|
|
73
|
+
lint: z.string().optional(),
|
|
74
|
+
/**
|
|
75
|
+
* Command to run type checks.
|
|
76
|
+
* Default: 'pnpm typecheck'
|
|
77
|
+
*/
|
|
78
|
+
typecheck: z.string().optional(),
|
|
79
|
+
/**
|
|
80
|
+
* Command to run format checks.
|
|
81
|
+
* Default: 'pnpm format:check'
|
|
82
|
+
*/
|
|
83
|
+
format: z.string().optional(),
|
|
84
|
+
});
|
|
14
85
|
/**
|
|
15
86
|
* WU-1325: Lock policy for lane-level WIP enforcement
|
|
16
87
|
*
|
|
@@ -306,6 +377,26 @@ export const GatesConfigSchema = z.object({
|
|
|
306
377
|
* When set, gates runner uses these instead of hardcoded commands.
|
|
307
378
|
*/
|
|
308
379
|
execution: GatesExecutionConfigSchema.optional(),
|
|
380
|
+
/**
|
|
381
|
+
* WU-1356: Configurable gate commands
|
|
382
|
+
* Replaces hard-coded turbo/vitest commands with user-configurable alternatives.
|
|
383
|
+
* Enables LumenFlow to work with npm/yarn/bun, Nx/plain scripts, Jest/Mocha, etc.
|
|
384
|
+
*/
|
|
385
|
+
commands: GatesCommandsConfigSchema.default(() => GatesCommandsConfigSchema.parse({})),
|
|
386
|
+
/**
|
|
387
|
+
* WU-1356: Ignore patterns for test runners
|
|
388
|
+
* Patterns to ignore when detecting changed tests.
|
|
389
|
+
* Default: ['.turbo'] for vitest (derived from test_runner if not specified)
|
|
390
|
+
*/
|
|
391
|
+
ignore_patterns: z.array(z.string()).optional(),
|
|
392
|
+
/**
|
|
393
|
+
* WU-1191: Lane health gate mode
|
|
394
|
+
* Controls how lane health check behaves during gates.
|
|
395
|
+
* - 'warn': Log warning if issues found (default)
|
|
396
|
+
* - 'error': Fail gates if issues found
|
|
397
|
+
* - 'off': Skip lane health check
|
|
398
|
+
*/
|
|
399
|
+
lane_health: z.enum(['warn', 'error', 'off']).default('warn'),
|
|
309
400
|
});
|
|
310
401
|
/**
|
|
311
402
|
* WU-1203: Progress signals configuration for sub-agent coordination
|
|
@@ -731,6 +822,43 @@ export const LumenFlowConfigSchema = z.object({
|
|
|
731
822
|
* ```
|
|
732
823
|
*/
|
|
733
824
|
lanes: LanesConfigSchema.optional(),
|
|
825
|
+
/**
|
|
826
|
+
* WU-1356: Package manager for CLI operations
|
|
827
|
+
* Determines which package manager is used for build commands,
|
|
828
|
+
* dependency installation, and script execution.
|
|
829
|
+
*
|
|
830
|
+
* @default 'pnpm'
|
|
831
|
+
*
|
|
832
|
+
* @example
|
|
833
|
+
* ```yaml
|
|
834
|
+
* package_manager: npm
|
|
835
|
+
* ```
|
|
836
|
+
*/
|
|
837
|
+
package_manager: PackageManagerSchema,
|
|
838
|
+
/**
|
|
839
|
+
* WU-1356: Test runner for incremental test detection
|
|
840
|
+
* Determines how changed tests are detected and which ignore patterns to use.
|
|
841
|
+
*
|
|
842
|
+
* @default 'vitest'
|
|
843
|
+
*
|
|
844
|
+
* @example
|
|
845
|
+
* ```yaml
|
|
846
|
+
* test_runner: jest
|
|
847
|
+
* ```
|
|
848
|
+
*/
|
|
849
|
+
test_runner: TestRunnerSchema,
|
|
850
|
+
/**
|
|
851
|
+
* WU-1356: Custom build command for CLI bootstrap
|
|
852
|
+
* Overrides the default build command used in cli-entry.mjs.
|
|
853
|
+
*
|
|
854
|
+
* @default 'pnpm --filter @lumenflow/cli build'
|
|
855
|
+
*
|
|
856
|
+
* @example
|
|
857
|
+
* ```yaml
|
|
858
|
+
* build_command: 'npm run build'
|
|
859
|
+
* ```
|
|
860
|
+
*/
|
|
861
|
+
build_command: z.string().default('pnpm --filter @lumenflow/cli build'),
|
|
734
862
|
});
|
|
735
863
|
/**
|
|
736
864
|
* Validate configuration data
|
package/dist/wu-constants.d.ts
CHANGED
|
@@ -1718,6 +1718,75 @@ export declare const CONTEXT_VALIDATION: {
|
|
|
1718
1718
|
readonly GATES: "gates";
|
|
1719
1719
|
};
|
|
1720
1720
|
};
|
|
1721
|
+
/**
|
|
1722
|
+
* Git hook error messages (WU-1357)
|
|
1723
|
+
*
|
|
1724
|
+
* Educational, structured messages for git hook blocks.
|
|
1725
|
+
* Follows the "message bag" pattern: TITLE, WHY, ACTIONS, HELP, BYPASS.
|
|
1726
|
+
*
|
|
1727
|
+
* Design principles:
|
|
1728
|
+
* - Explain WHY before showing WHAT to do
|
|
1729
|
+
* - Provide multiple paths forward (not just one command)
|
|
1730
|
+
* - Put emergency bypass LAST with clear warnings
|
|
1731
|
+
* - Include help resources for learning
|
|
1732
|
+
*
|
|
1733
|
+
* @see .husky/hooks/pre-commit.mjs - Primary consumer
|
|
1734
|
+
*/
|
|
1735
|
+
export declare const HOOK_MESSAGES: {
|
|
1736
|
+
/**
|
|
1737
|
+
* Main branch protection block message components
|
|
1738
|
+
*/
|
|
1739
|
+
readonly MAIN_BRANCH_BLOCK: {
|
|
1740
|
+
/** Box drawing for visual structure */
|
|
1741
|
+
readonly BOX: {
|
|
1742
|
+
readonly TOP: "══════════════════════════════════════════════════════════════";
|
|
1743
|
+
readonly DIVIDER: "──────────────────────────────────────────────────────────────";
|
|
1744
|
+
};
|
|
1745
|
+
/** Title shown at the top */
|
|
1746
|
+
readonly TITLE: (branch: string) => string;
|
|
1747
|
+
/** Educational explanation of WHY the block exists */
|
|
1748
|
+
readonly WHY: {
|
|
1749
|
+
readonly HEADER: "WHY THIS HAPPENS";
|
|
1750
|
+
readonly LINES: readonly ["LumenFlow protects main from direct commits to ensure:", " • All work is tracked in Work Units (WUs)", " • Changes can be reviewed and coordinated", " • Parallel work across lanes stays isolated"];
|
|
1751
|
+
};
|
|
1752
|
+
/** Action paths - multiple ways forward */
|
|
1753
|
+
readonly ACTIONS: {
|
|
1754
|
+
readonly HEADER: "WHAT TO DO";
|
|
1755
|
+
readonly HAVE_WU: {
|
|
1756
|
+
readonly HEADER: "1. If you have a Work Unit to implement:";
|
|
1757
|
+
readonly COMMANDS: readonly ["pnpm wu:claim --id WU-XXXX --lane \"<Lane>\"", "cd worktrees/<lane>-wu-xxxx"];
|
|
1758
|
+
readonly NOTE: "Then make your commits there";
|
|
1759
|
+
};
|
|
1760
|
+
readonly NEED_WU: {
|
|
1761
|
+
readonly HEADER: "2. If you need to create a new Work Unit:";
|
|
1762
|
+
readonly COMMANDS: readonly ["pnpm wu:create --lane \"<Lane>\" --title \"Your task\""];
|
|
1763
|
+
readonly NOTE: "This generates a WU ID, then claim it as above";
|
|
1764
|
+
};
|
|
1765
|
+
readonly LIST_LANES: {
|
|
1766
|
+
readonly HEADER: "3. Not sure what lane to use?";
|
|
1767
|
+
readonly COMMANDS: readonly ["pnpm wu:list-lanes"];
|
|
1768
|
+
};
|
|
1769
|
+
};
|
|
1770
|
+
/** Help resources */
|
|
1771
|
+
readonly HELP: {
|
|
1772
|
+
readonly HEADER: "NEED HELP?";
|
|
1773
|
+
readonly RESOURCES: readonly ["• Read: LUMENFLOW.md (workflow overview)", "• Read: docs/04-operations/_frameworks/lumenflow/agent/onboarding/", "• Run: pnpm wu:help"];
|
|
1774
|
+
};
|
|
1775
|
+
/** Emergency bypass (shown last, with warnings) */
|
|
1776
|
+
readonly BYPASS: {
|
|
1777
|
+
readonly HEADER: "EMERGENCY BYPASS (logged, use sparingly)";
|
|
1778
|
+
readonly WARNING: "Bypasses are audit-logged. Only use for genuine emergencies.";
|
|
1779
|
+
readonly COMMAND: "LUMENFLOW_FORCE=1 LUMENFLOW_FORCE_REASON=\"<reason>\" git commit ...";
|
|
1780
|
+
};
|
|
1781
|
+
};
|
|
1782
|
+
/**
|
|
1783
|
+
* Worktree discipline block message components
|
|
1784
|
+
*/
|
|
1785
|
+
readonly WORKTREE_BLOCK: {
|
|
1786
|
+
readonly TITLE: "LANE BRANCH WORK SHOULD BE IN WORKTREE";
|
|
1787
|
+
readonly WHY: "Worktrees provide isolation for parallel work. Working on a lane branch from the main checkout bypasses this isolation.";
|
|
1788
|
+
};
|
|
1789
|
+
};
|
|
1721
1790
|
/** Type for location types */
|
|
1722
1791
|
export type LocationType = (typeof CONTEXT_VALIDATION.LOCATION_TYPES)[keyof typeof CONTEXT_VALIDATION.LOCATION_TYPES];
|
|
1723
1792
|
/** Type for validation error codes */
|
package/dist/wu-constants.js
CHANGED
|
@@ -1789,3 +1789,81 @@ export const CONTEXT_VALIDATION = {
|
|
|
1789
1789
|
GATES: 'gates',
|
|
1790
1790
|
},
|
|
1791
1791
|
};
|
|
1792
|
+
/**
|
|
1793
|
+
* Git hook error messages (WU-1357)
|
|
1794
|
+
*
|
|
1795
|
+
* Educational, structured messages for git hook blocks.
|
|
1796
|
+
* Follows the "message bag" pattern: TITLE, WHY, ACTIONS, HELP, BYPASS.
|
|
1797
|
+
*
|
|
1798
|
+
* Design principles:
|
|
1799
|
+
* - Explain WHY before showing WHAT to do
|
|
1800
|
+
* - Provide multiple paths forward (not just one command)
|
|
1801
|
+
* - Put emergency bypass LAST with clear warnings
|
|
1802
|
+
* - Include help resources for learning
|
|
1803
|
+
*
|
|
1804
|
+
* @see .husky/hooks/pre-commit.mjs - Primary consumer
|
|
1805
|
+
*/
|
|
1806
|
+
export const HOOK_MESSAGES = {
|
|
1807
|
+
/**
|
|
1808
|
+
* Main branch protection block message components
|
|
1809
|
+
*/
|
|
1810
|
+
MAIN_BRANCH_BLOCK: {
|
|
1811
|
+
/** Box drawing for visual structure */
|
|
1812
|
+
BOX: {
|
|
1813
|
+
TOP: '══════════════════════════════════════════════════════════════',
|
|
1814
|
+
DIVIDER: '──────────────────────────────────────────────────────────────',
|
|
1815
|
+
},
|
|
1816
|
+
/** Title shown at the top */
|
|
1817
|
+
TITLE: (branch) => `DIRECT COMMIT TO ${branch.toUpperCase()} BLOCKED`,
|
|
1818
|
+
/** Educational explanation of WHY the block exists */
|
|
1819
|
+
WHY: {
|
|
1820
|
+
HEADER: 'WHY THIS HAPPENS',
|
|
1821
|
+
LINES: [
|
|
1822
|
+
'LumenFlow protects main from direct commits to ensure:',
|
|
1823
|
+
' • All work is tracked in Work Units (WUs)',
|
|
1824
|
+
' • Changes can be reviewed and coordinated',
|
|
1825
|
+
' • Parallel work across lanes stays isolated',
|
|
1826
|
+
],
|
|
1827
|
+
},
|
|
1828
|
+
/** Action paths - multiple ways forward */
|
|
1829
|
+
ACTIONS: {
|
|
1830
|
+
HEADER: 'WHAT TO DO',
|
|
1831
|
+
HAVE_WU: {
|
|
1832
|
+
HEADER: '1. If you have a Work Unit to implement:',
|
|
1833
|
+
COMMANDS: ['pnpm wu:claim --id WU-XXXX --lane "<Lane>"', 'cd worktrees/<lane>-wu-xxxx'],
|
|
1834
|
+
NOTE: 'Then make your commits there',
|
|
1835
|
+
},
|
|
1836
|
+
NEED_WU: {
|
|
1837
|
+
HEADER: '2. If you need to create a new Work Unit:',
|
|
1838
|
+
COMMANDS: ['pnpm wu:create --lane "<Lane>" --title "Your task"'],
|
|
1839
|
+
NOTE: 'This generates a WU ID, then claim it as above',
|
|
1840
|
+
},
|
|
1841
|
+
LIST_LANES: {
|
|
1842
|
+
HEADER: '3. Not sure what lane to use?',
|
|
1843
|
+
COMMANDS: ['pnpm wu:list-lanes'],
|
|
1844
|
+
},
|
|
1845
|
+
},
|
|
1846
|
+
/** Help resources */
|
|
1847
|
+
HELP: {
|
|
1848
|
+
HEADER: 'NEED HELP?',
|
|
1849
|
+
RESOURCES: [
|
|
1850
|
+
'• Read: LUMENFLOW.md (workflow overview)',
|
|
1851
|
+
'• Read: docs/04-operations/_frameworks/lumenflow/agent/onboarding/',
|
|
1852
|
+
'• Run: pnpm wu:help',
|
|
1853
|
+
],
|
|
1854
|
+
},
|
|
1855
|
+
/** Emergency bypass (shown last, with warnings) */
|
|
1856
|
+
BYPASS: {
|
|
1857
|
+
HEADER: 'EMERGENCY BYPASS (logged, use sparingly)',
|
|
1858
|
+
WARNING: 'Bypasses are audit-logged. Only use for genuine emergencies.',
|
|
1859
|
+
COMMAND: 'LUMENFLOW_FORCE=1 LUMENFLOW_FORCE_REASON="<reason>" git commit ...',
|
|
1860
|
+
},
|
|
1861
|
+
},
|
|
1862
|
+
/**
|
|
1863
|
+
* Worktree discipline block message components
|
|
1864
|
+
*/
|
|
1865
|
+
WORKTREE_BLOCK: {
|
|
1866
|
+
TITLE: 'LANE BRANCH WORK SHOULD BE IN WORKTREE',
|
|
1867
|
+
WHY: 'Worktrees provide isolation for parallel work. Working on a lane branch from the main checkout bypasses this isolation.',
|
|
1868
|
+
},
|
|
1869
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lumenflow/core",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.6.0",
|
|
4
4
|
"description": "Core WU lifecycle tools for LumenFlow workflow framework",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"lumenflow",
|
|
@@ -99,7 +99,7 @@
|
|
|
99
99
|
"vitest": "^4.0.17"
|
|
100
100
|
},
|
|
101
101
|
"peerDependencies": {
|
|
102
|
-
"@lumenflow/memory": "2.
|
|
102
|
+
"@lumenflow/memory": "2.6.0"
|
|
103
103
|
},
|
|
104
104
|
"peerDependenciesMeta": {
|
|
105
105
|
"@lumenflow/memory": {
|