@lumenflow/cli 5.2.8 → 5.2.9
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/wu-create-validation.js +76 -4
- package/dist/wu-create-validation.js.map +1 -1
- package/package.json +11 -11
- package/packs/agent-runtime/package.json +1 -1
- package/packs/sidekick/package.json +1 -1
- package/packs/software-delivery/package.json +1 -1
- package/packs/software-delivery/src/policy/gates-config.ts +3 -0
- package/packs/software-delivery/src/policy/gates-coverage.ts +99 -0
|
@@ -16,6 +16,7 @@ import { validateWURulesSync } from '@lumenflow/core/wu-rules-engine';
|
|
|
16
16
|
import { validateNoPlaceholders, buildPlaceholderErrorMessage } from '@lumenflow/core/wu-validator';
|
|
17
17
|
import { isCodeFile } from '@lumenflow/core/manual-test-validator';
|
|
18
18
|
import { isDocsOrProcessType, hasManualTests } from '@lumenflow/core/wu-type-helpers';
|
|
19
|
+
import { evaluateTddDiffEvidenceWaiver, resolveTddDiffEvidencePolicy, } from '@lumenflow/packs-software-delivery/policy/gates-config';
|
|
19
20
|
import { buildWUContent } from './wu-create-content.js';
|
|
20
21
|
/** Log prefix for console output */
|
|
21
22
|
const LOG_PREFIX = '[wu:create]';
|
|
@@ -29,16 +30,55 @@ export function containsCodeFiles(codePaths) {
|
|
|
29
30
|
export function hasAnyItems(value) {
|
|
30
31
|
return Array.isArray(value) && value.length > 0;
|
|
31
32
|
}
|
|
33
|
+
/** Test-path keywords for filtering completeness errors when waived */
|
|
34
|
+
const TEST_PATH_ERROR_MARKERS = [
|
|
35
|
+
'test path required',
|
|
36
|
+
'tests.unit',
|
|
37
|
+
'tests.e2e',
|
|
38
|
+
'tests.integration',
|
|
39
|
+
'tests.manual',
|
|
40
|
+
'at least one test entry',
|
|
41
|
+
'at least one test path',
|
|
42
|
+
'no automated tests',
|
|
43
|
+
'requires test_paths',
|
|
44
|
+
'has no automated tests',
|
|
45
|
+
];
|
|
46
|
+
/**
|
|
47
|
+
* WU-2881: Identify test-path-related errors so we can suppress them when the
|
|
48
|
+
* resolved tdd_diff_evidence policy waives the requirement.
|
|
49
|
+
*
|
|
50
|
+
* Other completeness errors (description, code_paths, schema) MUST still
|
|
51
|
+
* surface — only test-path errors are policy-gated.
|
|
52
|
+
*/
|
|
53
|
+
function isTestPathRelatedError(error) {
|
|
54
|
+
const lower = error.toLowerCase();
|
|
55
|
+
return TEST_PATH_ERROR_MARKERS.some((marker) => lower.includes(marker.toLowerCase()));
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* WU-2881: Print a one-line audit-trail message when the test-path requirement
|
|
59
|
+
* is waived at create-time. Reviewers need to see at a glance WHY a feature WU
|
|
60
|
+
* shipped without tests.
|
|
61
|
+
*/
|
|
62
|
+
function logTestPathsWaived(waiver) {
|
|
63
|
+
console.log(`${LOG_PREFIX} Test paths waived: ${waiver.detail}`);
|
|
64
|
+
}
|
|
32
65
|
/**
|
|
33
66
|
* Validate WU spec for creation
|
|
34
67
|
*
|
|
35
68
|
* WU-1329: Strict mode (default) validates that code_paths and test_paths exist on disk.
|
|
36
69
|
* Use opts.strict = false to bypass path existence checks.
|
|
37
70
|
*
|
|
71
|
+
* WU-2881: Consults `software_delivery.gates.tdd_diff_evidence` to decide
|
|
72
|
+
* whether to enforce the test-path requirement. When the resolved policy
|
|
73
|
+
* waives the WU (mode=off, type not in applies_to_types, or all code_paths
|
|
74
|
+
* under exempt_paths), `tests.manual` is no longer required and downstream
|
|
75
|
+
* completeness errors about missing test paths are suppressed. An audit-trail
|
|
76
|
+
* line is printed in every waiver case so reviewers can see why.
|
|
77
|
+
*
|
|
38
78
|
* @param params - Validation parameters
|
|
39
79
|
* @returns {{ valid: boolean, errors: string[] }}
|
|
40
80
|
*/
|
|
41
|
-
export function validateCreateSpec({ id, lane, title, priority, type, opts, }) {
|
|
81
|
+
export function validateCreateSpec({ id, lane, title, priority, type, opts, projectRoot, policyResolver, }) {
|
|
42
82
|
const errors = [];
|
|
43
83
|
const effectiveType = type || DEFAULT_TYPE;
|
|
44
84
|
// WU-1329: Strict mode flag retained for backwards compatibility in CLI UX.
|
|
@@ -64,9 +104,26 @@ export function validateCreateSpec({ id, lane, title, priority, type, opts, }) {
|
|
|
64
104
|
errors.push('--code-paths is required for non-documentation WUs');
|
|
65
105
|
}
|
|
66
106
|
}
|
|
107
|
+
// WU-2881: Consult the configurable tdd_diff_evidence policy so wu:create
|
|
108
|
+
// agrees with the wu:prep diff-evidence gate. Documentation/process types
|
|
109
|
+
// remain unconditionally exempt (the carve-out below is independent of the
|
|
110
|
+
// policy and predates it).
|
|
111
|
+
let tddWaiver = { waived: false };
|
|
112
|
+
if (!isDocsOrProcessType(effectiveType)) {
|
|
113
|
+
const resolver = policyResolver ?? resolveTddDiffEvidencePolicy;
|
|
114
|
+
const policy = resolver(projectRoot ?? process.cwd());
|
|
115
|
+
tddWaiver = evaluateTddDiffEvidenceWaiver({
|
|
116
|
+
policy,
|
|
117
|
+
type: effectiveType,
|
|
118
|
+
codePaths: opts.codePaths ?? [],
|
|
119
|
+
});
|
|
120
|
+
}
|
|
67
121
|
// WU-2263: Enforce tests.manual for non-doc/process WUs at create time
|
|
68
122
|
// (aligns with wu:claim's validateManualTestsForClaim, WU-1508)
|
|
69
|
-
|
|
123
|
+
// WU-2881: Skip when the configurable tdd_diff_evidence policy waives the
|
|
124
|
+
// test-path requirement (mode=off / type not in applies_to_types / all
|
|
125
|
+
// code_paths under exempt_paths).
|
|
126
|
+
if (!isDocsOrProcessType(effectiveType) && !tddWaiver.waived) {
|
|
70
127
|
const tests = {
|
|
71
128
|
manual: opts.testPathsManual,
|
|
72
129
|
unit: opts.testPathsUnit,
|
|
@@ -77,6 +134,9 @@ export function validateCreateSpec({ id, lane, title, priority, type, opts, }) {
|
|
|
77
134
|
' Add at least one manual verification step under tests.manual.');
|
|
78
135
|
}
|
|
79
136
|
}
|
|
137
|
+
if (tddWaiver.waived) {
|
|
138
|
+
logTestPathsWaived(tddWaiver);
|
|
139
|
+
}
|
|
80
140
|
// WU-1755: --plan flag auto-generates a spec-ref at wu-create.ts:419 via mergeSpecRefs(),
|
|
81
141
|
// so skip this validation when --plan is provided (the ref will exist by the time YAML is written).
|
|
82
142
|
if (effectiveType === WU_TYPES.FEATURE && !hasSpecRefs(opts.specRefs) && !opts.plan) {
|
|
@@ -127,10 +187,22 @@ export function validateCreateSpec({ id, lane, title, priority, type, opts, }) {
|
|
|
127
187
|
code_paths: wuContent.code_paths,
|
|
128
188
|
tests: wuContent.tests,
|
|
129
189
|
}, { phase: 'intent' });
|
|
130
|
-
|
|
190
|
+
// WU-2881: Filter out test-path-related rule violations when the
|
|
191
|
+
// tdd_diff_evidence policy waives the WU. Other intent-rule errors
|
|
192
|
+
// (e.g. code-path validation) still surface.
|
|
193
|
+
const intentMessages = intentRules.errors.map((issue) => issue.message);
|
|
194
|
+
const filteredIntentMessages = tddWaiver.waived
|
|
195
|
+
? intentMessages.filter((msg) => !isTestPathRelatedError(msg))
|
|
196
|
+
: intentMessages;
|
|
197
|
+
errors.push(...filteredIntentMessages);
|
|
131
198
|
const completeness = validateSpecCompleteness(wuContent, id);
|
|
132
199
|
if (!completeness.valid) {
|
|
133
|
-
|
|
200
|
+
// WU-2881: When tdd_diff_evidence policy waives test paths, drop
|
|
201
|
+
// test-path-related completeness errors but keep all others.
|
|
202
|
+
const completenessErrors = tddWaiver.waived
|
|
203
|
+
? completeness.errors.filter((err) => !isTestPathRelatedError(err))
|
|
204
|
+
: completeness.errors;
|
|
205
|
+
errors.push(...completenessErrors);
|
|
134
206
|
}
|
|
135
207
|
}
|
|
136
208
|
if (errors.length > 0) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wu-create-validation.js","sourceRoot":"","sources":["../src/wu-create-validation.ts"],"names":[],"mappings":"AAAA,iCAAiC;AACjC,yCAAyC;AAEzC;;;;;;GAMG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAEtD,OAAO,EAAE,WAAW,EAAE,MAAM,sCAAsC,CAAC;AACnE,OAAO,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AACxD,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AACvD,OAAO,EAAE,wBAAwB,EAAE,MAAM,oCAAoC,CAAC;AAC9E,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,EAAE,sBAAsB,EAAE,4BAA4B,EAAE,MAAM,8BAA8B,CAAC;AACpG,OAAO,EAAE,UAAU,EAAE,MAAM,uCAAuC,CAAC;AACnE,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACtF,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAExD,oCAAoC;AACpC,MAAM,UAAU,GAAG,aAAa,CAAC;AAEjC,sBAAsB;AACtB,MAAM,YAAY,GAAG,QAAQ,CAAC,OAAO,CAAC;AAmCtC,MAAM,UAAU,iBAAiB,CAAC,SAA+B;IAC/D,IAAI,CAAC,SAAS,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACvD,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC;AAC5D,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,KAAc;IACxC,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;AAClD,CAAC;AAED
|
|
1
|
+
{"version":3,"file":"wu-create-validation.js","sourceRoot":"","sources":["../src/wu-create-validation.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lumenflow/cli",
|
|
3
|
-
"version": "5.2.
|
|
3
|
+
"version": "5.2.9",
|
|
4
4
|
"description": "Command-line interface for LumenFlow workflow framework",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"lumenflow",
|
|
@@ -197,16 +197,16 @@
|
|
|
197
197
|
"xstate": "^5.28.0",
|
|
198
198
|
"yaml": "^2.8.2",
|
|
199
199
|
"zod": "^4.3.6",
|
|
200
|
-
"@lumenflow/
|
|
201
|
-
"@lumenflow/
|
|
202
|
-
"@lumenflow/memory": "5.2.
|
|
203
|
-
"@lumenflow/
|
|
204
|
-
"@lumenflow/
|
|
205
|
-
"@lumenflow/
|
|
206
|
-
"@lumenflow/
|
|
207
|
-
"@lumenflow/
|
|
208
|
-
"@lumenflow/
|
|
209
|
-
"@lumenflow/packs-
|
|
200
|
+
"@lumenflow/initiatives": "5.2.9",
|
|
201
|
+
"@lumenflow/control-plane-sdk": "5.2.9",
|
|
202
|
+
"@lumenflow/memory": "5.2.9",
|
|
203
|
+
"@lumenflow/metrics": "5.2.9",
|
|
204
|
+
"@lumenflow/kernel": "5.2.9",
|
|
205
|
+
"@lumenflow/agent": "5.2.9",
|
|
206
|
+
"@lumenflow/core": "5.2.9",
|
|
207
|
+
"@lumenflow/packs-agent-runtime": "^5.2.9",
|
|
208
|
+
"@lumenflow/host": "^5.2.9",
|
|
209
|
+
"@lumenflow/packs-software-delivery": "^5.2.9"
|
|
210
210
|
},
|
|
211
211
|
"devDependencies": {
|
|
212
212
|
"@vitest/coverage-v8": "^4.0.18",
|
|
@@ -80,7 +80,10 @@ export {
|
|
|
80
80
|
resolveTestPolicy,
|
|
81
81
|
resolveTddDiffEvidencePolicy,
|
|
82
82
|
resolveTddOrderingPolicy,
|
|
83
|
+
evaluateTddDiffEvidenceWaiver,
|
|
84
|
+
isPathExemptByTddDiffEvidence,
|
|
83
85
|
} from './gates-coverage.js';
|
|
86
|
+
export type { TddDiffEvidenceWaiver, TddDiffEvidenceWaiverReason } from './gates-coverage.js';
|
|
84
87
|
|
|
85
88
|
// Re-export package manager / test runner resolution
|
|
86
89
|
export {
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
* @module gates-coverage
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
|
+
import { minimatch } from 'minimatch';
|
|
15
16
|
import { asRecord, isBoolean, isNumber } from '../constants/object-guards.js';
|
|
16
17
|
import {
|
|
17
18
|
resolvePolicy,
|
|
@@ -230,6 +231,104 @@ export function resolveTddDiffEvidencePolicy(projectRoot: string): TddDiffEviden
|
|
|
230
231
|
return resolvePolicyFromConfig(rawConfig).tdd_diff_evidence;
|
|
231
232
|
}
|
|
232
233
|
|
|
234
|
+
const TDD_GLOB_MATCH_OPTIONS = { dot: true } as const;
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Result of evaluating whether a WU is waived from the TDD diff-evidence
|
|
238
|
+
* test-path requirement based on the resolved tdd_diff_evidence policy.
|
|
239
|
+
*
|
|
240
|
+
* Used by both wu:create (test-path requirement) and wu:prep
|
|
241
|
+
* (diff-evidence enforcement) so that the two surfaces stay in lockstep.
|
|
242
|
+
*
|
|
243
|
+
* WU-2881: Surfacing the rationale via `reason` lets callers print an
|
|
244
|
+
* audit-trail line so reviewers can see WHY a WU bypassed test paths.
|
|
245
|
+
*/
|
|
246
|
+
export type TddDiffEvidenceWaiver =
|
|
247
|
+
| { waived: false }
|
|
248
|
+
| { waived: true; reason: TddDiffEvidenceWaiverReason; detail: string };
|
|
249
|
+
|
|
250
|
+
export type TddDiffEvidenceWaiverReason = 'mode-off' | 'type-not-applicable' | 'all-paths-exempt';
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* WU-2881: Pure helper used by wu:create (and reusable by wu:prep) to decide
|
|
254
|
+
* whether the resolved tdd_diff_evidence policy waives the test-path
|
|
255
|
+
* requirement for a given WU shape.
|
|
256
|
+
*
|
|
257
|
+
* Returns waived=true when ANY of the following hold:
|
|
258
|
+
* 1. policy.mode === 'off'
|
|
259
|
+
* 2. policy.applies_to_types does not include the WU's type
|
|
260
|
+
* 3. The WU has at least one code_path AND every code_path matches one of
|
|
261
|
+
* policy.exempt_paths globs
|
|
262
|
+
*
|
|
263
|
+
* Mixed cases (some code_paths exempt, others not) are NOT waived — strict
|
|
264
|
+
* behavior preserved per WU-2881 acceptance criteria.
|
|
265
|
+
*/
|
|
266
|
+
export function evaluateTddDiffEvidenceWaiver(options: {
|
|
267
|
+
policy: TddDiffEvidencePolicy;
|
|
268
|
+
type: string | undefined;
|
|
269
|
+
codePaths: readonly string[];
|
|
270
|
+
}): TddDiffEvidenceWaiver {
|
|
271
|
+
const { policy, type, codePaths } = options;
|
|
272
|
+
|
|
273
|
+
if (policy.mode === 'off') {
|
|
274
|
+
return {
|
|
275
|
+
waived: true,
|
|
276
|
+
reason: 'mode-off',
|
|
277
|
+
detail: 'tdd_diff_evidence.mode=off (workspace.yaml)',
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
if (typeof type !== 'string' || !policy.applies_to_types.some((t) => t === type)) {
|
|
282
|
+
return {
|
|
283
|
+
waived: true,
|
|
284
|
+
reason: 'type-not-applicable',
|
|
285
|
+
detail: `WU type '${type ?? '<unknown>'}' not in tdd_diff_evidence.applies_to_types=[${policy.applies_to_types.join(', ')}]`,
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
if (codePaths.length > 0 && policy.exempt_paths.length > 0) {
|
|
290
|
+
const matchedPatterns = new Set<string>();
|
|
291
|
+
const allExempt = codePaths.every((codePath) => {
|
|
292
|
+
const normalized = codePath.replace(/\\/g, '/');
|
|
293
|
+
const matchedPattern = policy.exempt_paths.find((pattern) =>
|
|
294
|
+
minimatch(normalized, pattern, TDD_GLOB_MATCH_OPTIONS),
|
|
295
|
+
);
|
|
296
|
+
if (matchedPattern) {
|
|
297
|
+
matchedPatterns.add(matchedPattern);
|
|
298
|
+
return true;
|
|
299
|
+
}
|
|
300
|
+
return false;
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
if (allExempt) {
|
|
304
|
+
return {
|
|
305
|
+
waived: true,
|
|
306
|
+
reason: 'all-paths-exempt',
|
|
307
|
+
detail: `all code_paths under exempt_paths globs (${[...matchedPatterns].join(', ')})`,
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
return { waived: false };
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* WU-2881: Match a single file path against the policy's exempt_paths globs.
|
|
317
|
+
*
|
|
318
|
+
* Centralizes the minimatch invocation so wu:prep and other callers can share
|
|
319
|
+
* one canonical exempt-path matcher.
|
|
320
|
+
*/
|
|
321
|
+
export function isPathExemptByTddDiffEvidence(
|
|
322
|
+
filePath: string,
|
|
323
|
+
exemptPaths: readonly string[],
|
|
324
|
+
): boolean {
|
|
325
|
+
if (exemptPaths.length === 0) {
|
|
326
|
+
return false;
|
|
327
|
+
}
|
|
328
|
+
const normalized = filePath.replace(/\\/g, '/');
|
|
329
|
+
return exemptPaths.some((pattern) => minimatch(normalized, pattern, TDD_GLOB_MATCH_OPTIONS));
|
|
330
|
+
}
|
|
331
|
+
|
|
233
332
|
/**
|
|
234
333
|
* WU-2650: Resolve the commit-order (RED-first) policy.
|
|
235
334
|
*
|