@lumenflow/core 1.0.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/LICENSE +190 -0
- package/README.md +119 -0
- package/dist/active-wu-detector.d.ts +33 -0
- package/dist/active-wu-detector.js +106 -0
- package/dist/adapters/filesystem-metrics.adapter.d.ts +108 -0
- package/dist/adapters/filesystem-metrics.adapter.js +519 -0
- package/dist/adapters/terminal-renderer.adapter.d.ts +106 -0
- package/dist/adapters/terminal-renderer.adapter.js +337 -0
- package/dist/arg-parser.d.ts +63 -0
- package/dist/arg-parser.js +560 -0
- package/dist/backlog-editor.d.ts +98 -0
- package/dist/backlog-editor.js +179 -0
- package/dist/backlog-generator.d.ts +111 -0
- package/dist/backlog-generator.js +381 -0
- package/dist/backlog-parser.d.ts +45 -0
- package/dist/backlog-parser.js +102 -0
- package/dist/backlog-sync-validator.d.ts +78 -0
- package/dist/backlog-sync-validator.js +294 -0
- package/dist/branch-drift.d.ts +34 -0
- package/dist/branch-drift.js +51 -0
- package/dist/cleanup-install-config.d.ts +33 -0
- package/dist/cleanup-install-config.js +37 -0
- package/dist/cleanup-lock.d.ts +139 -0
- package/dist/cleanup-lock.js +313 -0
- package/dist/code-path-validator.d.ts +146 -0
- package/dist/code-path-validator.js +537 -0
- package/dist/code-paths-overlap.d.ts +55 -0
- package/dist/code-paths-overlap.js +245 -0
- package/dist/commands-logger.d.ts +77 -0
- package/dist/commands-logger.js +254 -0
- package/dist/commit-message-utils.d.ts +25 -0
- package/dist/commit-message-utils.js +41 -0
- package/dist/compliance-parser.d.ts +150 -0
- package/dist/compliance-parser.js +507 -0
- package/dist/constants/backlog-patterns.d.ts +20 -0
- package/dist/constants/backlog-patterns.js +23 -0
- package/dist/constants/dora-constants.d.ts +49 -0
- package/dist/constants/dora-constants.js +53 -0
- package/dist/constants/gate-constants.d.ts +15 -0
- package/dist/constants/gate-constants.js +15 -0
- package/dist/constants/linter-constants.d.ts +16 -0
- package/dist/constants/linter-constants.js +16 -0
- package/dist/constants/tokenizer-constants.d.ts +15 -0
- package/dist/constants/tokenizer-constants.js +15 -0
- package/dist/core/scope-checker.d.ts +97 -0
- package/dist/core/scope-checker.js +163 -0
- package/dist/core/tool-runner.d.ts +161 -0
- package/dist/core/tool-runner.js +393 -0
- package/dist/core/tool.constants.d.ts +105 -0
- package/dist/core/tool.constants.js +101 -0
- package/dist/core/tool.schemas.d.ts +226 -0
- package/dist/core/tool.schemas.js +226 -0
- package/dist/core/worktree-guard.d.ts +130 -0
- package/dist/core/worktree-guard.js +242 -0
- package/dist/coverage-gate.d.ts +108 -0
- package/dist/coverage-gate.js +196 -0
- package/dist/date-utils.d.ts +75 -0
- package/dist/date-utils.js +140 -0
- package/dist/dependency-graph.d.ts +142 -0
- package/dist/dependency-graph.js +550 -0
- package/dist/dependency-guard.d.ts +54 -0
- package/dist/dependency-guard.js +142 -0
- package/dist/dependency-validator.d.ts +105 -0
- package/dist/dependency-validator.js +154 -0
- package/dist/docs-path-validator.d.ts +36 -0
- package/dist/docs-path-validator.js +95 -0
- package/dist/domain/orchestration.constants.d.ts +99 -0
- package/dist/domain/orchestration.constants.js +97 -0
- package/dist/domain/orchestration.schemas.d.ts +280 -0
- package/dist/domain/orchestration.schemas.js +211 -0
- package/dist/domain/orchestration.types.d.ts +133 -0
- package/dist/domain/orchestration.types.js +12 -0
- package/dist/error-handler.d.ts +116 -0
- package/dist/error-handler.js +136 -0
- package/dist/file-classifiers.d.ts +62 -0
- package/dist/file-classifiers.js +108 -0
- package/dist/gates-agent-mode.d.ts +81 -0
- package/dist/gates-agent-mode.js +94 -0
- package/dist/generate-traceability.d.ts +107 -0
- package/dist/generate-traceability.js +411 -0
- package/dist/git-adapter.d.ts +395 -0
- package/dist/git-adapter.js +649 -0
- package/dist/git-staged-validator.d.ts +32 -0
- package/dist/git-staged-validator.js +48 -0
- package/dist/hardcoded-strings.d.ts +61 -0
- package/dist/hardcoded-strings.js +270 -0
- package/dist/incremental-lint.d.ts +78 -0
- package/dist/incremental-lint.js +129 -0
- package/dist/incremental-test.d.ts +39 -0
- package/dist/incremental-test.js +61 -0
- package/dist/index.d.ts +42 -0
- package/dist/index.js +61 -0
- package/dist/invariants/check-automated-tests.d.ts +50 -0
- package/dist/invariants/check-automated-tests.js +166 -0
- package/dist/invariants-runner.d.ts +103 -0
- package/dist/invariants-runner.js +527 -0
- package/dist/lane-checker.d.ts +50 -0
- package/dist/lane-checker.js +319 -0
- package/dist/lane-inference.d.ts +39 -0
- package/dist/lane-inference.js +195 -0
- package/dist/lane-lock.d.ts +211 -0
- package/dist/lane-lock.js +474 -0
- package/dist/lane-validator.d.ts +48 -0
- package/dist/lane-validator.js +114 -0
- package/dist/logs-lib.d.ts +104 -0
- package/dist/logs-lib.js +207 -0
- package/dist/lumenflow-config-schema.d.ts +272 -0
- package/dist/lumenflow-config-schema.js +207 -0
- package/dist/lumenflow-config.d.ts +95 -0
- package/dist/lumenflow-config.js +236 -0
- package/dist/manual-test-validator.d.ts +80 -0
- package/dist/manual-test-validator.js +200 -0
- package/dist/merge-lock.d.ts +115 -0
- package/dist/merge-lock.js +251 -0
- package/dist/micro-worktree.d.ts +159 -0
- package/dist/micro-worktree.js +427 -0
- package/dist/migration-deployer.d.ts +69 -0
- package/dist/migration-deployer.js +151 -0
- package/dist/orchestration-advisory-loader.d.ts +28 -0
- package/dist/orchestration-advisory-loader.js +87 -0
- package/dist/orchestration-advisory.d.ts +58 -0
- package/dist/orchestration-advisory.js +94 -0
- package/dist/orchestration-di.d.ts +48 -0
- package/dist/orchestration-di.js +57 -0
- package/dist/orchestration-rules.d.ts +57 -0
- package/dist/orchestration-rules.js +201 -0
- package/dist/orphan-detector.d.ts +131 -0
- package/dist/orphan-detector.js +226 -0
- package/dist/path-classifiers.d.ts +57 -0
- package/dist/path-classifiers.js +93 -0
- package/dist/piped-command-detector.d.ts +34 -0
- package/dist/piped-command-detector.js +64 -0
- package/dist/ports/dashboard-renderer.port.d.ts +112 -0
- package/dist/ports/dashboard-renderer.port.js +25 -0
- package/dist/ports/metrics-collector.port.d.ts +132 -0
- package/dist/ports/metrics-collector.port.js +26 -0
- package/dist/process-detector.d.ts +84 -0
- package/dist/process-detector.js +172 -0
- package/dist/prompt-linter.d.ts +72 -0
- package/dist/prompt-linter.js +312 -0
- package/dist/prompt-monitor.d.ts +15 -0
- package/dist/prompt-monitor.js +205 -0
- package/dist/rebase-artifact-cleanup.d.ts +145 -0
- package/dist/rebase-artifact-cleanup.js +433 -0
- package/dist/retry-strategy.d.ts +189 -0
- package/dist/retry-strategy.js +283 -0
- package/dist/risk-detector.d.ts +108 -0
- package/dist/risk-detector.js +252 -0
- package/dist/rollback-utils.d.ts +76 -0
- package/dist/rollback-utils.js +104 -0
- package/dist/section-headings.d.ts +43 -0
- package/dist/section-headings.js +49 -0
- package/dist/spawn-escalation.d.ts +90 -0
- package/dist/spawn-escalation.js +253 -0
- package/dist/spawn-monitor.d.ts +229 -0
- package/dist/spawn-monitor.js +672 -0
- package/dist/spawn-recovery.d.ts +82 -0
- package/dist/spawn-recovery.js +298 -0
- package/dist/spawn-registry-schema.d.ts +98 -0
- package/dist/spawn-registry-schema.js +108 -0
- package/dist/spawn-registry-store.d.ts +146 -0
- package/dist/spawn-registry-store.js +273 -0
- package/dist/spawn-tree.d.ts +121 -0
- package/dist/spawn-tree.js +285 -0
- package/dist/stamp-status-validator.d.ts +84 -0
- package/dist/stamp-status-validator.js +134 -0
- package/dist/stamp-utils.d.ts +100 -0
- package/dist/stamp-utils.js +229 -0
- package/dist/state-machine.d.ts +26 -0
- package/dist/state-machine.js +83 -0
- package/dist/system-map-validator.d.ts +80 -0
- package/dist/system-map-validator.js +272 -0
- package/dist/telemetry.d.ts +80 -0
- package/dist/telemetry.js +213 -0
- package/dist/token-counter.d.ts +51 -0
- package/dist/token-counter.js +145 -0
- package/dist/usecases/get-dashboard-data.usecase.d.ts +52 -0
- package/dist/usecases/get-dashboard-data.usecase.js +61 -0
- package/dist/usecases/get-suggestions.usecase.d.ts +100 -0
- package/dist/usecases/get-suggestions.usecase.js +153 -0
- package/dist/user-normalizer.d.ts +41 -0
- package/dist/user-normalizer.js +141 -0
- package/dist/validators/phi-constants.d.ts +97 -0
- package/dist/validators/phi-constants.js +152 -0
- package/dist/validators/phi-scanner.d.ts +58 -0
- package/dist/validators/phi-scanner.js +215 -0
- package/dist/worktree-ownership.d.ts +50 -0
- package/dist/worktree-ownership.js +74 -0
- package/dist/worktree-scanner.d.ts +103 -0
- package/dist/worktree-scanner.js +168 -0
- package/dist/worktree-symlink.d.ts +99 -0
- package/dist/worktree-symlink.js +359 -0
- package/dist/wu-backlog-updater.d.ts +17 -0
- package/dist/wu-backlog-updater.js +37 -0
- package/dist/wu-checkpoint.d.ts +124 -0
- package/dist/wu-checkpoint.js +233 -0
- package/dist/wu-claim-helpers.d.ts +26 -0
- package/dist/wu-claim-helpers.js +63 -0
- package/dist/wu-claim-resume.d.ts +106 -0
- package/dist/wu-claim-resume.js +276 -0
- package/dist/wu-consistency-checker.d.ts +95 -0
- package/dist/wu-consistency-checker.js +567 -0
- package/dist/wu-constants.d.ts +1275 -0
- package/dist/wu-constants.js +1382 -0
- package/dist/wu-create-validators.d.ts +42 -0
- package/dist/wu-create-validators.js +93 -0
- package/dist/wu-done-branch-only.d.ts +63 -0
- package/dist/wu-done-branch-only.js +191 -0
- package/dist/wu-done-messages.d.ts +119 -0
- package/dist/wu-done-messages.js +185 -0
- package/dist/wu-done-pr.d.ts +72 -0
- package/dist/wu-done-pr.js +174 -0
- package/dist/wu-done-retry-helpers.d.ts +85 -0
- package/dist/wu-done-retry-helpers.js +172 -0
- package/dist/wu-done-ui.d.ts +37 -0
- package/dist/wu-done-ui.js +69 -0
- package/dist/wu-done-validators.d.ts +411 -0
- package/dist/wu-done-validators.js +1229 -0
- package/dist/wu-done-worktree.d.ts +182 -0
- package/dist/wu-done-worktree.js +1097 -0
- package/dist/wu-helpers.d.ts +128 -0
- package/dist/wu-helpers.js +248 -0
- package/dist/wu-lint.d.ts +70 -0
- package/dist/wu-lint.js +234 -0
- package/dist/wu-paths.d.ts +171 -0
- package/dist/wu-paths.js +178 -0
- package/dist/wu-preflight-validators.d.ts +86 -0
- package/dist/wu-preflight-validators.js +251 -0
- package/dist/wu-recovery.d.ts +138 -0
- package/dist/wu-recovery.js +341 -0
- package/dist/wu-repair-core.d.ts +131 -0
- package/dist/wu-repair-core.js +669 -0
- package/dist/wu-schema-normalization.d.ts +17 -0
- package/dist/wu-schema-normalization.js +82 -0
- package/dist/wu-schema.d.ts +793 -0
- package/dist/wu-schema.js +881 -0
- package/dist/wu-spawn-helpers.d.ts +121 -0
- package/dist/wu-spawn-helpers.js +271 -0
- package/dist/wu-spawn.d.ts +158 -0
- package/dist/wu-spawn.js +1306 -0
- package/dist/wu-state-schema.d.ts +213 -0
- package/dist/wu-state-schema.js +156 -0
- package/dist/wu-state-store.d.ts +264 -0
- package/dist/wu-state-store.js +691 -0
- package/dist/wu-status-transition.d.ts +63 -0
- package/dist/wu-status-transition.js +382 -0
- package/dist/wu-status-updater.d.ts +25 -0
- package/dist/wu-status-updater.js +116 -0
- package/dist/wu-transaction-collectors.d.ts +116 -0
- package/dist/wu-transaction-collectors.js +272 -0
- package/dist/wu-transaction.d.ts +170 -0
- package/dist/wu-transaction.js +273 -0
- package/dist/wu-validation-constants.d.ts +60 -0
- package/dist/wu-validation-constants.js +66 -0
- package/dist/wu-validation.d.ts +118 -0
- package/dist/wu-validation.js +243 -0
- package/dist/wu-validator.d.ts +62 -0
- package/dist/wu-validator.js +325 -0
- package/dist/wu-yaml-fixer.d.ts +97 -0
- package/dist/wu-yaml-fixer.js +264 -0
- package/dist/wu-yaml.d.ts +86 -0
- package/dist/wu-yaml.js +222 -0
- package/package.json +114 -0
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WU Paths - Centralized path management for Work Units
|
|
3
|
+
*
|
|
4
|
+
* All paths are configurable via .lumenflow.config.yaml
|
|
5
|
+
*
|
|
6
|
+
* @module wu-paths
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Resolve repo root from an absolute file path by traversing up N directory levels.
|
|
10
|
+
*
|
|
11
|
+
* @param absolutePath - Absolute path to a file within the repo
|
|
12
|
+
* @param depth - Number of directory levels to traverse up
|
|
13
|
+
* @returns Absolute path to repo root
|
|
14
|
+
*/
|
|
15
|
+
export declare function resolveRepoRoot(absolutePath: string, depth: number): string;
|
|
16
|
+
/**
|
|
17
|
+
* Get the state store directory path from backlog.md path.
|
|
18
|
+
*
|
|
19
|
+
* @param backlogPath - Absolute path to backlog.md
|
|
20
|
+
* @returns Absolute path to state store directory
|
|
21
|
+
*/
|
|
22
|
+
export declare function getStateStoreDirFromBacklog(backlogPath: string): string;
|
|
23
|
+
/**
|
|
24
|
+
* Create WU paths object with configurable base paths
|
|
25
|
+
*
|
|
26
|
+
* @param options - Options for path generation
|
|
27
|
+
* @param options.projectRoot - Override project root
|
|
28
|
+
* @returns WU paths object
|
|
29
|
+
*/
|
|
30
|
+
export declare function createWuPaths(options?: {
|
|
31
|
+
projectRoot?: string;
|
|
32
|
+
}): {
|
|
33
|
+
/**
|
|
34
|
+
* Get path to WU YAML file
|
|
35
|
+
* @param id - WU ID (e.g., 'WU-123')
|
|
36
|
+
* @returns Path to WU YAML file
|
|
37
|
+
*/
|
|
38
|
+
WU: (id: string) => string;
|
|
39
|
+
/**
|
|
40
|
+
* Get path to WU directory
|
|
41
|
+
* @returns Path to WU directory
|
|
42
|
+
*/
|
|
43
|
+
WU_DIR: () => string;
|
|
44
|
+
/**
|
|
45
|
+
* Get path to status.md
|
|
46
|
+
* @returns Path to status.md
|
|
47
|
+
*/
|
|
48
|
+
STATUS: () => string;
|
|
49
|
+
/**
|
|
50
|
+
* Get path to backlog.md
|
|
51
|
+
* @returns Path to backlog.md
|
|
52
|
+
*/
|
|
53
|
+
BACKLOG: () => string;
|
|
54
|
+
/**
|
|
55
|
+
* Get path to stamps directory
|
|
56
|
+
* @returns Path to stamps directory
|
|
57
|
+
*/
|
|
58
|
+
STAMPS_DIR: () => string;
|
|
59
|
+
/**
|
|
60
|
+
* Get path to WU done stamp file
|
|
61
|
+
* @param id - WU ID (e.g., 'WU-123')
|
|
62
|
+
* @returns Path to stamp file
|
|
63
|
+
*/
|
|
64
|
+
STAMP: (id: string) => string;
|
|
65
|
+
/**
|
|
66
|
+
* Get path to state directory
|
|
67
|
+
* @returns Path to state directory
|
|
68
|
+
*/
|
|
69
|
+
STATE_DIR: () => string;
|
|
70
|
+
/**
|
|
71
|
+
* Get path to initiatives directory
|
|
72
|
+
* @returns Path to initiatives directory
|
|
73
|
+
*/
|
|
74
|
+
INITIATIVES_DIR: () => string;
|
|
75
|
+
/**
|
|
76
|
+
* Get path to worktrees directory
|
|
77
|
+
* @returns Path to worktrees directory
|
|
78
|
+
*/
|
|
79
|
+
WORKTREES_DIR: () => string;
|
|
80
|
+
};
|
|
81
|
+
/**
|
|
82
|
+
* Default WU paths using default config
|
|
83
|
+
* For backwards compatibility with existing code
|
|
84
|
+
*/
|
|
85
|
+
export declare const WU_PATHS: {
|
|
86
|
+
/**
|
|
87
|
+
* Get path to WU YAML file
|
|
88
|
+
* @param id - WU ID (e.g., 'WU-123')
|
|
89
|
+
* @returns Path to WU YAML file
|
|
90
|
+
*/
|
|
91
|
+
WU: (id: string) => string;
|
|
92
|
+
/**
|
|
93
|
+
* Get path to WU directory
|
|
94
|
+
* @returns Path to WU directory
|
|
95
|
+
*/
|
|
96
|
+
WU_DIR: () => string;
|
|
97
|
+
/**
|
|
98
|
+
* Get path to status.md
|
|
99
|
+
* @returns Path to status.md
|
|
100
|
+
*/
|
|
101
|
+
STATUS: () => string;
|
|
102
|
+
/**
|
|
103
|
+
* Get path to backlog.md
|
|
104
|
+
* @returns Path to backlog.md
|
|
105
|
+
*/
|
|
106
|
+
BACKLOG: () => string;
|
|
107
|
+
/**
|
|
108
|
+
* Get path to stamps directory
|
|
109
|
+
* @returns Path to stamps directory
|
|
110
|
+
*/
|
|
111
|
+
STAMPS_DIR: () => string;
|
|
112
|
+
/**
|
|
113
|
+
* Get path to WU done stamp file
|
|
114
|
+
* @param id - WU ID (e.g., 'WU-123')
|
|
115
|
+
* @returns Path to stamp file
|
|
116
|
+
*/
|
|
117
|
+
STAMP: (id: string) => string;
|
|
118
|
+
/**
|
|
119
|
+
* Get path to state directory
|
|
120
|
+
* @returns Path to state directory
|
|
121
|
+
*/
|
|
122
|
+
STATE_DIR: () => string;
|
|
123
|
+
/**
|
|
124
|
+
* Get path to initiatives directory
|
|
125
|
+
* @returns Path to initiatives directory
|
|
126
|
+
*/
|
|
127
|
+
INITIATIVES_DIR: () => string;
|
|
128
|
+
/**
|
|
129
|
+
* Get path to worktrees directory
|
|
130
|
+
* @returns Path to worktrees directory
|
|
131
|
+
*/
|
|
132
|
+
WORKTREES_DIR: () => string;
|
|
133
|
+
};
|
|
134
|
+
/**
|
|
135
|
+
* Generate default worktree path from WU document
|
|
136
|
+
*
|
|
137
|
+
* @param doc - WU document with lane and id fields
|
|
138
|
+
* @returns Worktree path or null if inputs are invalid
|
|
139
|
+
*/
|
|
140
|
+
export declare function defaultWorktreeFrom(doc: {
|
|
141
|
+
lane?: string;
|
|
142
|
+
id?: string;
|
|
143
|
+
} | null | undefined): string | null;
|
|
144
|
+
/**
|
|
145
|
+
* Resolve a repo-root-relative path to an absolute path using project root.
|
|
146
|
+
*
|
|
147
|
+
* @param relativePath - Path relative to project root
|
|
148
|
+
* @param moduleUrl - import.meta.url of the calling module (for backwards compat)
|
|
149
|
+
* @returns Absolute path resolved from project root
|
|
150
|
+
*/
|
|
151
|
+
export declare function resolveFromProjectRoot(relativePath: string, moduleUrl?: string): string;
|
|
152
|
+
/**
|
|
153
|
+
* Get absolute path to WU YAML file
|
|
154
|
+
*
|
|
155
|
+
* @param id - WU ID (e.g., 'WU-123')
|
|
156
|
+
* @param options - Options
|
|
157
|
+
* @returns Absolute path to WU YAML file
|
|
158
|
+
*/
|
|
159
|
+
export declare function getAbsoluteWuPath(id: string, options?: {
|
|
160
|
+
projectRoot?: string;
|
|
161
|
+
}): string;
|
|
162
|
+
/**
|
|
163
|
+
* Get absolute path to stamp file
|
|
164
|
+
*
|
|
165
|
+
* @param id - WU ID (e.g., 'WU-123')
|
|
166
|
+
* @param options - Options
|
|
167
|
+
* @returns Absolute path to stamp file
|
|
168
|
+
*/
|
|
169
|
+
export declare function getAbsoluteStampPath(id: string, options?: {
|
|
170
|
+
projectRoot?: string;
|
|
171
|
+
}): string;
|
package/dist/wu-paths.js
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WU Paths - Centralized path management for Work Units
|
|
3
|
+
*
|
|
4
|
+
* All paths are configurable via .lumenflow.config.yaml
|
|
5
|
+
*
|
|
6
|
+
* @module wu-paths
|
|
7
|
+
*/
|
|
8
|
+
import * as path from 'node:path';
|
|
9
|
+
import { getWorktreePath, getProjectRoot as getProjectRootFromConstants } from './wu-constants.js';
|
|
10
|
+
import { getConfig, getProjectRoot as getProjectRootFromConfig } from './lumenflow-config.js';
|
|
11
|
+
/**
|
|
12
|
+
* Directory depth constants for path resolution.
|
|
13
|
+
* These define how many levels deep each standard file is from repo root.
|
|
14
|
+
*/
|
|
15
|
+
const PATH_DEPTHS = {
|
|
16
|
+
/** backlog.md is 4 levels deep: docs/04-operations/tasks/backlog.md */
|
|
17
|
+
BACKLOG: 4,
|
|
18
|
+
/** status.md is 4 levels deep: docs/04-operations/tasks/status.md */
|
|
19
|
+
STATUS: 4,
|
|
20
|
+
/** WU YAML files are 5 levels deep: docs/04-operations/tasks/wu/{id}.yaml */
|
|
21
|
+
WU_YAML: 5,
|
|
22
|
+
/** State store is 3 levels deep: .beacon/state/wu-events.jsonl */
|
|
23
|
+
STATE_STORE: 3,
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Resolve repo root from an absolute file path by traversing up N directory levels.
|
|
27
|
+
*
|
|
28
|
+
* @param absolutePath - Absolute path to a file within the repo
|
|
29
|
+
* @param depth - Number of directory levels to traverse up
|
|
30
|
+
* @returns Absolute path to repo root
|
|
31
|
+
*/
|
|
32
|
+
export function resolveRepoRoot(absolutePath, depth) {
|
|
33
|
+
let result = absolutePath;
|
|
34
|
+
for (let i = 0; i < depth; i++) {
|
|
35
|
+
result = path.dirname(result);
|
|
36
|
+
}
|
|
37
|
+
return result;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Get the state store directory path from backlog.md path.
|
|
41
|
+
*
|
|
42
|
+
* @param backlogPath - Absolute path to backlog.md
|
|
43
|
+
* @returns Absolute path to state store directory
|
|
44
|
+
*/
|
|
45
|
+
export function getStateStoreDirFromBacklog(backlogPath) {
|
|
46
|
+
const config = getConfig();
|
|
47
|
+
const repoRoot = resolveRepoRoot(backlogPath, PATH_DEPTHS.BACKLOG);
|
|
48
|
+
return path.join(repoRoot, config.beacon.stateDir);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Create WU paths object with configurable base paths
|
|
52
|
+
*
|
|
53
|
+
* @param options - Options for path generation
|
|
54
|
+
* @param options.projectRoot - Override project root
|
|
55
|
+
* @returns WU paths object
|
|
56
|
+
*/
|
|
57
|
+
export function createWuPaths(options = {}) {
|
|
58
|
+
const config = getConfig({ projectRoot: options.projectRoot });
|
|
59
|
+
return {
|
|
60
|
+
/**
|
|
61
|
+
* Get path to WU YAML file
|
|
62
|
+
* @param id - WU ID (e.g., 'WU-123')
|
|
63
|
+
* @returns Path to WU YAML file
|
|
64
|
+
*/
|
|
65
|
+
WU: (id) => path.join(config.directories.wuDir, `${id}.yaml`),
|
|
66
|
+
/**
|
|
67
|
+
* Get path to WU directory
|
|
68
|
+
* @returns Path to WU directory
|
|
69
|
+
*/
|
|
70
|
+
WU_DIR: () => config.directories.wuDir,
|
|
71
|
+
/**
|
|
72
|
+
* Get path to status.md
|
|
73
|
+
* @returns Path to status.md
|
|
74
|
+
*/
|
|
75
|
+
STATUS: () => config.directories.statusPath,
|
|
76
|
+
/**
|
|
77
|
+
* Get path to backlog.md
|
|
78
|
+
* @returns Path to backlog.md
|
|
79
|
+
*/
|
|
80
|
+
BACKLOG: () => config.directories.backlogPath,
|
|
81
|
+
/**
|
|
82
|
+
* Get path to stamps directory
|
|
83
|
+
* @returns Path to stamps directory
|
|
84
|
+
*/
|
|
85
|
+
STAMPS_DIR: () => config.beacon.stampsDir,
|
|
86
|
+
/**
|
|
87
|
+
* Get path to WU done stamp file
|
|
88
|
+
* @param id - WU ID (e.g., 'WU-123')
|
|
89
|
+
* @returns Path to stamp file
|
|
90
|
+
*/
|
|
91
|
+
STAMP: (id) => path.join(config.beacon.stampsDir, `${id}.done`),
|
|
92
|
+
/**
|
|
93
|
+
* Get path to state directory
|
|
94
|
+
* @returns Path to state directory
|
|
95
|
+
*/
|
|
96
|
+
STATE_DIR: () => config.beacon.stateDir,
|
|
97
|
+
/**
|
|
98
|
+
* Get path to initiatives directory
|
|
99
|
+
* @returns Path to initiatives directory
|
|
100
|
+
*/
|
|
101
|
+
INITIATIVES_DIR: () => config.directories.initiativesDir,
|
|
102
|
+
/**
|
|
103
|
+
* Get path to worktrees directory
|
|
104
|
+
* @returns Path to worktrees directory
|
|
105
|
+
*/
|
|
106
|
+
WORKTREES_DIR: () => config.directories.worktrees,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Default WU paths using default config
|
|
111
|
+
* For backwards compatibility with existing code
|
|
112
|
+
*/
|
|
113
|
+
export const WU_PATHS = createWuPaths();
|
|
114
|
+
/**
|
|
115
|
+
* Generate default worktree path from WU document
|
|
116
|
+
*
|
|
117
|
+
* @param doc - WU document with lane and id fields
|
|
118
|
+
* @returns Worktree path or null if inputs are invalid
|
|
119
|
+
*/
|
|
120
|
+
export function defaultWorktreeFrom(doc) {
|
|
121
|
+
if (!doc)
|
|
122
|
+
return null;
|
|
123
|
+
const lane = doc.lane;
|
|
124
|
+
const id = doc.id;
|
|
125
|
+
// Validate inputs
|
|
126
|
+
if (!lane || !id)
|
|
127
|
+
return null;
|
|
128
|
+
// Convert to string and trim
|
|
129
|
+
const laneStr = String(lane).trim();
|
|
130
|
+
const idStr = String(id).trim();
|
|
131
|
+
// Check for empty strings after trimming
|
|
132
|
+
if (laneStr === '' || idStr === '')
|
|
133
|
+
return null;
|
|
134
|
+
// Use centralized getWorktreePath from wu-constants
|
|
135
|
+
return getWorktreePath(laneStr, idStr);
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Resolve a repo-root-relative path to an absolute path using project root.
|
|
139
|
+
*
|
|
140
|
+
* @param relativePath - Path relative to project root
|
|
141
|
+
* @param moduleUrl - import.meta.url of the calling module (for backwards compat)
|
|
142
|
+
* @returns Absolute path resolved from project root
|
|
143
|
+
*/
|
|
144
|
+
export function resolveFromProjectRoot(relativePath, moduleUrl) {
|
|
145
|
+
// Try config-based project root first, fall back to constants-based
|
|
146
|
+
let projectRoot;
|
|
147
|
+
try {
|
|
148
|
+
projectRoot = getProjectRootFromConfig();
|
|
149
|
+
}
|
|
150
|
+
catch {
|
|
151
|
+
projectRoot = moduleUrl ? getProjectRootFromConstants(moduleUrl) : process.cwd();
|
|
152
|
+
}
|
|
153
|
+
return path.join(projectRoot, relativePath);
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Get absolute path to WU YAML file
|
|
157
|
+
*
|
|
158
|
+
* @param id - WU ID (e.g., 'WU-123')
|
|
159
|
+
* @param options - Options
|
|
160
|
+
* @returns Absolute path to WU YAML file
|
|
161
|
+
*/
|
|
162
|
+
export function getAbsoluteWuPath(id, options = {}) {
|
|
163
|
+
const projectRoot = options.projectRoot || getProjectRootFromConfig();
|
|
164
|
+
const paths = createWuPaths({ projectRoot });
|
|
165
|
+
return path.join(projectRoot, paths.WU(id));
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Get absolute path to stamp file
|
|
169
|
+
*
|
|
170
|
+
* @param id - WU ID (e.g., 'WU-123')
|
|
171
|
+
* @param options - Options
|
|
172
|
+
* @returns Absolute path to stamp file
|
|
173
|
+
*/
|
|
174
|
+
export function getAbsoluteStampPath(id, options = {}) {
|
|
175
|
+
const projectRoot = options.projectRoot || getProjectRootFromConfig();
|
|
176
|
+
const paths = createWuPaths({ projectRoot });
|
|
177
|
+
return path.join(projectRoot, paths.STAMP(id));
|
|
178
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Preflight validation functions for wu:preflight command
|
|
4
|
+
*
|
|
5
|
+
* WU-1803: Fast validation of code_paths and test paths before gates run.
|
|
6
|
+
* WU-1810: Upgraded to use canonical Zod schema validation (catches created format issues).
|
|
7
|
+
*
|
|
8
|
+
* This catches YAML mismatches early, saving time compared to full wu:done validation.
|
|
9
|
+
*
|
|
10
|
+
* Key validations:
|
|
11
|
+
* - WU YAML schema is valid (full canonical schema, not just required fields)
|
|
12
|
+
* - created field is YYYY-MM-DD format (fails fast on ISO timestamps)
|
|
13
|
+
* - code_paths files exist
|
|
14
|
+
* - test file paths exist (unit, e2e, integration - not manual)
|
|
15
|
+
*
|
|
16
|
+
* Design goals:
|
|
17
|
+
* - Complete in under 5 seconds
|
|
18
|
+
* - Clear error messages pointing to missing files
|
|
19
|
+
* - Reusable by wu:done for early validation
|
|
20
|
+
*/
|
|
21
|
+
/**
|
|
22
|
+
* Result structure for preflight validation
|
|
23
|
+
* @typedef {object} PreflightResult
|
|
24
|
+
* @property {boolean} valid - Whether all validations passed
|
|
25
|
+
* @property {string[]} errors - List of error messages
|
|
26
|
+
* @property {string[]} missingCodePaths - Code paths that don't exist
|
|
27
|
+
* @property {string[]} missingTestPaths - Test file paths that don't exist
|
|
28
|
+
*/
|
|
29
|
+
/**
|
|
30
|
+
* Create a PreflightResult object
|
|
31
|
+
*
|
|
32
|
+
* @param {object} params - Result parameters
|
|
33
|
+
* @param {boolean} params.valid - Whether validation passed
|
|
34
|
+
* @param {string[]} [params.errors=[]] - Error messages
|
|
35
|
+
* @param {string[]} [params.missingCodePaths=[]] - Missing code paths
|
|
36
|
+
* @param {string[]} [params.missingTestPaths=[]] - Missing test paths
|
|
37
|
+
* @returns {PreflightResult}
|
|
38
|
+
*/
|
|
39
|
+
export declare function createPreflightResult({ valid, errors, missingCodePaths, missingTestPaths, }: {
|
|
40
|
+
valid: any;
|
|
41
|
+
errors?: any[];
|
|
42
|
+
missingCodePaths?: any[];
|
|
43
|
+
missingTestPaths?: any[];
|
|
44
|
+
}): {
|
|
45
|
+
valid: any;
|
|
46
|
+
errors: any[];
|
|
47
|
+
missingCodePaths: any[];
|
|
48
|
+
missingTestPaths: any[];
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Run preflight validation for a WU
|
|
52
|
+
*
|
|
53
|
+
* Validates:
|
|
54
|
+
* 1. WU YAML schema is valid
|
|
55
|
+
* 2. code_paths files exist
|
|
56
|
+
* 3. test file paths exist (unit, e2e, integration)
|
|
57
|
+
*
|
|
58
|
+
* WU-1830: When worktreePath is provided, YAML is read from worktree (not rootDir).
|
|
59
|
+
* This ensures that when agent runs wu:edit to update code_paths in worktree,
|
|
60
|
+
* preflight validation uses the updated YAML, not stale main.
|
|
61
|
+
*
|
|
62
|
+
* @param {string} id - WU ID (e.g., 'WU-999')
|
|
63
|
+
* @param {ValidatePreflightOptions} [options={}] - Options
|
|
64
|
+
* @returns {Promise<PreflightResult>}
|
|
65
|
+
*/
|
|
66
|
+
export interface ValidatePreflightOptions {
|
|
67
|
+
/** Root directory for path resolution (fallback) */
|
|
68
|
+
rootDir?: string;
|
|
69
|
+
/** Worktree path (preferred source for YAML and file checks) */
|
|
70
|
+
worktreePath?: string | null;
|
|
71
|
+
}
|
|
72
|
+
export declare function validatePreflight(id: any, options?: ValidatePreflightOptions): Promise<{
|
|
73
|
+
valid: any;
|
|
74
|
+
errors: any[];
|
|
75
|
+
missingCodePaths: any[];
|
|
76
|
+
missingTestPaths: any[];
|
|
77
|
+
}>;
|
|
78
|
+
/**
|
|
79
|
+
* Format preflight result as user-friendly message
|
|
80
|
+
*
|
|
81
|
+
* @param {string} id - WU ID
|
|
82
|
+
* @param {PreflightResult} result - Validation result
|
|
83
|
+
* @returns {string} Formatted message
|
|
84
|
+
*/
|
|
85
|
+
export declare function formatPreflightResult(id: any, result: any): string;
|
|
86
|
+
export declare const PreflightResult: {};
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Preflight validation functions for wu:preflight command
|
|
4
|
+
*
|
|
5
|
+
* WU-1803: Fast validation of code_paths and test paths before gates run.
|
|
6
|
+
* WU-1810: Upgraded to use canonical Zod schema validation (catches created format issues).
|
|
7
|
+
*
|
|
8
|
+
* This catches YAML mismatches early, saving time compared to full wu:done validation.
|
|
9
|
+
*
|
|
10
|
+
* Key validations:
|
|
11
|
+
* - WU YAML schema is valid (full canonical schema, not just required fields)
|
|
12
|
+
* - created field is YYYY-MM-DD format (fails fast on ISO timestamps)
|
|
13
|
+
* - code_paths files exist
|
|
14
|
+
* - test file paths exist (unit, e2e, integration - not manual)
|
|
15
|
+
*
|
|
16
|
+
* Design goals:
|
|
17
|
+
* - Complete in under 5 seconds
|
|
18
|
+
* - Clear error messages pointing to missing files
|
|
19
|
+
* - Reusable by wu:done for early validation
|
|
20
|
+
*/
|
|
21
|
+
/* eslint-disable security/detect-non-literal-fs-filename, security/detect-object-injection */
|
|
22
|
+
import { existsSync } from 'node:fs';
|
|
23
|
+
import path from 'node:path';
|
|
24
|
+
import { WU_PATHS } from './wu-paths.js';
|
|
25
|
+
import { readWURaw } from './wu-yaml.js';
|
|
26
|
+
import { TEST_TYPES, LOG_PREFIX, EMOJI } from './wu-constants.js';
|
|
27
|
+
// WU-1810: Import canonical schema for full validation
|
|
28
|
+
import { BaseWUSchema } from './wu-schema.js';
|
|
29
|
+
// WU-1810: Import fixer to detect fixable issues
|
|
30
|
+
import { detectFixableIssues, FIXABLE_ISSUES } from './wu-yaml-fixer.js';
|
|
31
|
+
/**
|
|
32
|
+
* Result structure for preflight validation
|
|
33
|
+
* @typedef {object} PreflightResult
|
|
34
|
+
* @property {boolean} valid - Whether all validations passed
|
|
35
|
+
* @property {string[]} errors - List of error messages
|
|
36
|
+
* @property {string[]} missingCodePaths - Code paths that don't exist
|
|
37
|
+
* @property {string[]} missingTestPaths - Test file paths that don't exist
|
|
38
|
+
*/
|
|
39
|
+
/**
|
|
40
|
+
* Create a PreflightResult object
|
|
41
|
+
*
|
|
42
|
+
* @param {object} params - Result parameters
|
|
43
|
+
* @param {boolean} params.valid - Whether validation passed
|
|
44
|
+
* @param {string[]} [params.errors=[]] - Error messages
|
|
45
|
+
* @param {string[]} [params.missingCodePaths=[]] - Missing code paths
|
|
46
|
+
* @param {string[]} [params.missingTestPaths=[]] - Missing test paths
|
|
47
|
+
* @returns {PreflightResult}
|
|
48
|
+
*/
|
|
49
|
+
export function createPreflightResult({ valid, errors = [], missingCodePaths = [], missingTestPaths = [], }) {
|
|
50
|
+
return {
|
|
51
|
+
valid,
|
|
52
|
+
errors,
|
|
53
|
+
missingCodePaths,
|
|
54
|
+
missingTestPaths,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* WU-1810: Validate WU YAML schema using canonical Zod schema
|
|
59
|
+
*
|
|
60
|
+
* Uses BaseWUSchema (structural validation) rather than minimal required fields.
|
|
61
|
+
* This catches created format issues, invalid type/status enums, etc. early.
|
|
62
|
+
*
|
|
63
|
+
* Special handling for created field:
|
|
64
|
+
* - Detects ISO timestamps and Date scalars via wu-yaml-fixer
|
|
65
|
+
* - Provides actionable error message suggesting auto-fix
|
|
66
|
+
*
|
|
67
|
+
* @param {object} doc - Parsed WU YAML document
|
|
68
|
+
* @param {string} id - Expected WU ID
|
|
69
|
+
* @returns {{ valid: boolean, errors: string[] }}
|
|
70
|
+
*/
|
|
71
|
+
function validateSchema(doc, id) {
|
|
72
|
+
const errors = [];
|
|
73
|
+
// Check ID matches (before schema validation for clear error)
|
|
74
|
+
if (doc.id !== id) {
|
|
75
|
+
errors.push(`WU ID mismatch: expected ${id}, found ${doc.id}`);
|
|
76
|
+
}
|
|
77
|
+
// WU-1810: Check for fixable issues (especially created field)
|
|
78
|
+
// This provides better error messages than raw Zod schema errors
|
|
79
|
+
const fixableIssues = detectFixableIssues(doc);
|
|
80
|
+
const createdIssue = fixableIssues.find((issue) => issue.type === FIXABLE_ISSUES.DATE_ISO_TIMESTAMP);
|
|
81
|
+
if (createdIssue) {
|
|
82
|
+
errors.push(`created field has invalid format: "${createdIssue.current}" is an ISO timestamp. ` +
|
|
83
|
+
`Expected YYYY-MM-DD format. Suggested fix: change to "${createdIssue.suggested}". ` +
|
|
84
|
+
`Fix by editing the WU YAML file (created: '${createdIssue.suggested}').`);
|
|
85
|
+
}
|
|
86
|
+
// WU-1810: Validate against canonical Zod schema
|
|
87
|
+
const schemaResult = BaseWUSchema.safeParse(doc);
|
|
88
|
+
if (!schemaResult.success) {
|
|
89
|
+
// Format Zod errors with field paths
|
|
90
|
+
for (const issue of schemaResult.error.issues) {
|
|
91
|
+
const fieldPath = issue.path.join('.');
|
|
92
|
+
const message = issue.message;
|
|
93
|
+
// Skip created errors if we already reported a fixable issue
|
|
94
|
+
if (fieldPath === 'created' && createdIssue) {
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
errors.push(`${fieldPath}: ${message}`);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return { valid: errors.length === 0, errors };
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Validate code_paths files exist
|
|
104
|
+
*
|
|
105
|
+
* @param {string[]} codePaths - List of code paths from WU YAML
|
|
106
|
+
* @param {string} rootDir - Root directory to resolve paths against
|
|
107
|
+
* @returns {{ valid: boolean, errors: string[], missing: string[] }}
|
|
108
|
+
*/
|
|
109
|
+
function validateCodePathsExistence(codePaths, rootDir) {
|
|
110
|
+
if (!codePaths || !Array.isArray(codePaths) || codePaths.length === 0) {
|
|
111
|
+
return { valid: true, errors: [], missing: [] };
|
|
112
|
+
}
|
|
113
|
+
const missing = [];
|
|
114
|
+
for (const filePath of codePaths) {
|
|
115
|
+
if (!filePath || typeof filePath !== 'string')
|
|
116
|
+
continue;
|
|
117
|
+
const fullPath = path.join(rootDir, filePath);
|
|
118
|
+
if (!existsSync(fullPath)) {
|
|
119
|
+
missing.push(filePath);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
if (missing.length > 0) {
|
|
123
|
+
const errors = [
|
|
124
|
+
`code_paths validation failed - ${missing.length} file(s) not found:`,
|
|
125
|
+
...missing.map((p) => ` - ${p}`),
|
|
126
|
+
];
|
|
127
|
+
return { valid: false, errors, missing };
|
|
128
|
+
}
|
|
129
|
+
return { valid: true, errors: [], missing: [] };
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Validate test file paths exist (unit, e2e, integration - not manual)
|
|
133
|
+
*
|
|
134
|
+
* Manual tests are descriptions, not file paths, so they're skipped.
|
|
135
|
+
*
|
|
136
|
+
* @param {object} tests - tests object from WU YAML
|
|
137
|
+
* @param {string} rootDir - Root directory to resolve paths against
|
|
138
|
+
* @returns {{ valid: boolean, errors: string[], missing: string[] }}
|
|
139
|
+
*/
|
|
140
|
+
function validateTestPathsExistence(tests, rootDir) {
|
|
141
|
+
if (!tests || typeof tests !== 'object') {
|
|
142
|
+
return { valid: true, errors: [], missing: [] };
|
|
143
|
+
}
|
|
144
|
+
const missing = [];
|
|
145
|
+
// Test types that are file paths (not manual descriptions)
|
|
146
|
+
const fileTestTypes = [TEST_TYPES.UNIT, TEST_TYPES.E2E, TEST_TYPES.INTEGRATION];
|
|
147
|
+
for (const testType of fileTestTypes) {
|
|
148
|
+
const paths = tests[testType];
|
|
149
|
+
if (!paths || !Array.isArray(paths))
|
|
150
|
+
continue;
|
|
151
|
+
for (const filePath of paths) {
|
|
152
|
+
if (!filePath || typeof filePath !== 'string')
|
|
153
|
+
continue;
|
|
154
|
+
const fullPath = path.join(rootDir, filePath);
|
|
155
|
+
if (!existsSync(fullPath)) {
|
|
156
|
+
missing.push(filePath);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
if (missing.length > 0) {
|
|
161
|
+
const errors = [
|
|
162
|
+
`test paths validation failed - ${missing.length} test file(s) not found:`,
|
|
163
|
+
...missing.map((p) => ` - ${p}`),
|
|
164
|
+
];
|
|
165
|
+
return { valid: false, errors, missing };
|
|
166
|
+
}
|
|
167
|
+
return { valid: true, errors: [], missing: [] };
|
|
168
|
+
}
|
|
169
|
+
export async function validatePreflight(id, options = {}) {
|
|
170
|
+
const rootDir = options.rootDir || process.cwd();
|
|
171
|
+
const worktreePath = options.worktreePath || rootDir;
|
|
172
|
+
const allErrors = [];
|
|
173
|
+
const missingCodePaths = [];
|
|
174
|
+
const missingTestPaths = [];
|
|
175
|
+
// Step 1: Read WU YAML from worktree (WU-1830)
|
|
176
|
+
// When worktreePath is provided, read YAML from there to get latest code_paths
|
|
177
|
+
const wuPath = path.join(worktreePath, WU_PATHS.WU(id));
|
|
178
|
+
// Debug logging for YAML source (WU-1830)
|
|
179
|
+
if (options.worktreePath && options.worktreePath !== rootDir) {
|
|
180
|
+
process.env.DEBUG && console.log(`[wu-preflight] Reading WU YAML from worktree: ${wuPath}`);
|
|
181
|
+
}
|
|
182
|
+
let doc;
|
|
183
|
+
try {
|
|
184
|
+
// First try to read raw (without ID validation) to provide better errors
|
|
185
|
+
doc = readWURaw(wuPath);
|
|
186
|
+
}
|
|
187
|
+
catch (err) {
|
|
188
|
+
return createPreflightResult({
|
|
189
|
+
valid: false,
|
|
190
|
+
errors: [`Failed to read WU YAML: ${err.message}`],
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
// Step 2: Validate schema
|
|
194
|
+
const schemaResult = validateSchema(doc, id);
|
|
195
|
+
if (!schemaResult.valid) {
|
|
196
|
+
allErrors.push(...schemaResult.errors);
|
|
197
|
+
}
|
|
198
|
+
// Step 3: Validate code_paths exist
|
|
199
|
+
const codePathsResult = validateCodePathsExistence(doc.code_paths, worktreePath);
|
|
200
|
+
if (!codePathsResult.valid) {
|
|
201
|
+
allErrors.push(...codePathsResult.errors);
|
|
202
|
+
missingCodePaths.push(...codePathsResult.missing);
|
|
203
|
+
}
|
|
204
|
+
// Step 4: Validate test file paths exist
|
|
205
|
+
// Support both 'tests' and legacy 'test_paths' field
|
|
206
|
+
const testsObj = doc.tests || doc.test_paths || {};
|
|
207
|
+
const testPathsResult = validateTestPathsExistence(testsObj, worktreePath);
|
|
208
|
+
if (!testPathsResult.valid) {
|
|
209
|
+
allErrors.push(...testPathsResult.errors);
|
|
210
|
+
missingTestPaths.push(...testPathsResult.missing);
|
|
211
|
+
}
|
|
212
|
+
return createPreflightResult({
|
|
213
|
+
valid: allErrors.length === 0,
|
|
214
|
+
errors: allErrors,
|
|
215
|
+
missingCodePaths,
|
|
216
|
+
missingTestPaths,
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Format preflight result as user-friendly message
|
|
221
|
+
*
|
|
222
|
+
* @param {string} id - WU ID
|
|
223
|
+
* @param {PreflightResult} result - Validation result
|
|
224
|
+
* @returns {string} Formatted message
|
|
225
|
+
*/
|
|
226
|
+
export function formatPreflightResult(id, result) {
|
|
227
|
+
if (result.valid) {
|
|
228
|
+
return `${LOG_PREFIX.PREFLIGHT} ${EMOJI.SUCCESS} Preflight validation passed for ${id}`;
|
|
229
|
+
}
|
|
230
|
+
const lines = [
|
|
231
|
+
`${LOG_PREFIX.PREFLIGHT} ${EMOJI.FAILURE} Preflight validation failed for ${id}`,
|
|
232
|
+
'',
|
|
233
|
+
...result.errors,
|
|
234
|
+
];
|
|
235
|
+
if (result.missingCodePaths.length > 0) {
|
|
236
|
+
lines.push('');
|
|
237
|
+
lines.push('Fix options:');
|
|
238
|
+
lines.push(' 1. Create the missing files');
|
|
239
|
+
lines.push(` 2. Update code_paths in ${id}.yaml to match actual files`);
|
|
240
|
+
}
|
|
241
|
+
if (result.missingTestPaths.length > 0) {
|
|
242
|
+
lines.push('');
|
|
243
|
+
lines.push('For test paths:');
|
|
244
|
+
lines.push(' 1. Create the missing test files');
|
|
245
|
+
lines.push(` 2. Update tests in ${id}.yaml to match actual files`);
|
|
246
|
+
lines.push(' 3. Or use tests.manual for non-file test descriptions');
|
|
247
|
+
}
|
|
248
|
+
return lines.join('\n');
|
|
249
|
+
}
|
|
250
|
+
// Export PreflightResult type for documentation
|
|
251
|
+
export const PreflightResult = {};
|