@webpieces/dev-config 0.2.75 → 0.2.77

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.
Files changed (37) hide show
  1. package/architecture/executors/validate-code/executor.d.ts +14 -6
  2. package/architecture/executors/validate-code/executor.js +61 -37
  3. package/architecture/executors/validate-code/executor.js.map +1 -1
  4. package/architecture/executors/validate-code/executor.ts +94 -58
  5. package/architecture/executors/validate-code/schema.json +48 -29
  6. package/architecture/executors/validate-modified-files/executor.d.ts +4 -3
  7. package/architecture/executors/validate-modified-files/executor.js +32 -30
  8. package/architecture/executors/validate-modified-files/executor.js.map +1 -1
  9. package/architecture/executors/validate-modified-files/executor.ts +36 -33
  10. package/architecture/executors/validate-modified-files/schema.json +9 -4
  11. package/architecture/executors/validate-modified-methods/executor.d.ts +7 -6
  12. package/architecture/executors/validate-modified-methods/executor.js +53 -47
  13. package/architecture/executors/validate-modified-methods/executor.js.map +1 -1
  14. package/architecture/executors/validate-modified-methods/executor.ts +57 -51
  15. package/architecture/executors/validate-modified-methods/schema.json +10 -5
  16. package/architecture/executors/validate-new-methods/executor.d.ts +4 -4
  17. package/architecture/executors/validate-new-methods/executor.js +64 -83
  18. package/architecture/executors/validate-new-methods/executor.js.map +1 -1
  19. package/architecture/executors/validate-new-methods/executor.ts +75 -96
  20. package/architecture/executors/validate-new-methods/schema.json +11 -10
  21. package/architecture/executors/validate-no-any-unknown/executor.d.ts +1 -2
  22. package/architecture/executors/validate-no-any-unknown/executor.js +57 -55
  23. package/architecture/executors/validate-no-any-unknown/executor.js.map +1 -1
  24. package/architecture/executors/validate-no-any-unknown/executor.ts +62 -57
  25. package/architecture/executors/validate-no-any-unknown/schema.json +2 -2
  26. package/architecture/executors/validate-no-inline-types/executor.d.ts +1 -2
  27. package/architecture/executors/validate-no-inline-types/executor.js +25 -58
  28. package/architecture/executors/validate-no-inline-types/executor.js.map +1 -1
  29. package/architecture/executors/validate-no-inline-types/executor.ts +26 -59
  30. package/architecture/executors/validate-no-inline-types/schema.json +2 -2
  31. package/architecture/executors/validate-return-types/executor.d.ts +1 -2
  32. package/architecture/executors/validate-return-types/executor.js +25 -58
  33. package/architecture/executors/validate-return-types/executor.js.map +1 -1
  34. package/architecture/executors/validate-return-types/executor.ts +26 -59
  35. package/architecture/executors/validate-return-types/schema.json +2 -2
  36. package/package.json +1 -1
  37. package/plugin.js +24 -7
@@ -5,10 +5,10 @@
5
5
  * This encourages gradual cleanup of legacy long methods - when you touch a method,
6
6
  * you must bring it under the limit.
7
7
  *
8
- * Combined with validate-new-methods (30 line limit), this creates a gradual
8
+ * Combined with validate-new-methods, this creates a gradual
9
9
  * transition to cleaner code:
10
- * - New methods: strict 30 line limit
11
- * - Modified methods: lenient 80 line limit (cleanup when touched)
10
+ * - New methods: must be under limit
11
+ * - Modified methods: must be under limit (cleanup when touched)
12
12
  * - Untouched methods: no limit (legacy allowed)
13
13
  *
14
14
  * Usage:
@@ -25,11 +25,12 @@ import * as fs from 'fs';
25
25
  import * as path from 'path';
26
26
  import * as ts from 'typescript';
27
27
 
28
- export type ValidationMode = 'STRICT' | 'NORMAL' | 'OFF';
28
+ export type MethodMaxLimitMode = 'OFF' | 'NEW_METHODS' | 'NEW_AND_MODIFIED_METHODS' | 'MODIFIED_FILES';
29
29
 
30
30
  export interface ValidateModifiedMethodsOptions {
31
- max?: number;
32
- mode?: ValidationMode;
31
+ limit?: number;
32
+ mode?: MethodMaxLimitMode;
33
+ disableAllowed?: boolean;
33
34
  }
34
35
 
35
36
  export interface ExecutorResult {
@@ -52,10 +53,8 @@ const METHODSIZE_DOC_CONTENT = `# Instructions: Method Too Long
52
53
 
53
54
  ## Requirement
54
55
 
55
- **~50% of the time**, you can stay under the \`newMethodsMaxLines\` limit from nx.json
56
+ **~99% of the time**, you can stay under the \`limit\` from nx.json
56
57
  by extracting logical units into well-named methods.
57
-
58
- **~99% of the time**, you can stay under the \`modifiedAndNewMethodsMaxLines\` limit from nx.json.
59
58
  Nearly all software can be written with methods under this size.
60
59
  Take the extra time to refactor - it's worth it for long-term maintainability.
61
60
 
@@ -78,8 +77,8 @@ Methods under reasonable limits are:
78
77
  ## Gradual Cleanup Strategy
79
78
 
80
79
  This codebase uses a gradual cleanup approach:
81
- - **New methods**: Must be under \`newMethodsMaxLines\` from nx.json
82
- - **Modified methods**: Must be under \`modifiedAndNewMethodsMaxLines\` from nx.json
80
+ - **New methods**: Must be under \`limit\` from nx.json
81
+ - **Modified methods**: Must be under \`limit\` from nx.json
83
82
  - **Untouched methods**: No limit (legacy code is allowed until touched)
84
83
 
85
84
  ## How to Refactor
@@ -557,11 +556,11 @@ function methodHasChanges(method: MethodInfo, changedLineNumbers: Set<number>):
557
556
  /**
558
557
  * Check a NEW method and return violation if applicable
559
558
  */
560
- function checkNewMethodViolation(file: string, method: MethodInfo, mode: ValidationMode): MethodViolation | null {
559
+ function checkNewMethodViolation(file: string, method: MethodInfo, disableAllowed: boolean): MethodViolation | null {
561
560
  const { type: disableType, isExpired, date: disableDate } = method.disableInfo;
562
561
 
563
- if (mode === 'STRICT') {
564
- // When mode is STRICT, skip NEW methods without escape (let validate-new-methods handle)
562
+ if (!disableAllowed) {
563
+ // When disableAllowed is false, skip NEW methods without escape (let validate-new-methods handle)
565
564
  if (disableType === 'none') return null;
566
565
  return { file, methodName: method.name, line: method.line, lines: method.lines };
567
566
  }
@@ -580,12 +579,16 @@ function checkNewMethodViolation(file: string, method: MethodInfo, mode: Validat
580
579
  /**
581
580
  * Check a MODIFIED method and return violation if applicable
582
581
  */
583
- function checkModifiedMethodViolation(file: string, method: MethodInfo, mode: ValidationMode): MethodViolation {
582
+ function checkModifiedMethodViolation(file: string, method: MethodInfo, disableAllowed: boolean): MethodViolation | null {
584
583
  const { type: disableType, isExpired, date: disableDate } = method.disableInfo;
585
584
 
586
- if (mode === 'STRICT') {
585
+ if (!disableAllowed) {
587
586
  return { file, methodName: method.name, line: method.line, lines: method.lines };
588
587
  }
588
+ if (disableType === 'full' && !isExpired) {
589
+ // Valid escape, no violation
590
+ return null;
591
+ }
589
592
  if (disableType === 'full' && isExpired) {
590
593
  return { file, methodName: method.name, line: method.line, lines: method.lines, expiredDisable: true, expiredDate: disableDate };
591
594
  }
@@ -593,15 +596,15 @@ function checkModifiedMethodViolation(file: string, method: MethodInfo, mode: Va
593
596
  }
594
597
 
595
598
  /**
596
- * Find methods that exceed the 80-line limit.
599
+ * Find methods that exceed the limit.
597
600
  * Checks NEW methods with escape hatches and MODIFIED methods.
598
601
  */
599
602
  function findViolations(
600
603
  workspaceRoot: string,
601
604
  changedFiles: string[],
602
605
  base: string,
603
- maxLines: number,
604
- mode: ValidationMode,
606
+ limit: number,
607
+ disableAllowed: boolean,
605
608
  head?: string
606
609
  ): MethodViolation[] {
607
610
  const violations: MethodViolation[] = [];
@@ -619,17 +622,18 @@ function findViolations(
619
622
  for (const method of methods) {
620
623
  const { type: disableType, isExpired } = method.disableInfo;
621
624
 
622
- // Skip methods with valid, non-expired full escape - unless mode is STRICT
623
- if (mode !== 'STRICT' && disableType === 'full' && !isExpired) continue;
624
- if (method.lines <= maxLines) continue;
625
+ // Skip methods with valid, non-expired full escape - unless disableAllowed is false
626
+ if (disableAllowed && disableType === 'full' && !isExpired) continue;
627
+ if (method.lines <= limit) continue;
625
628
 
626
629
  const isNewMethod = newMethodNames.has(method.name);
627
630
 
628
631
  if (isNewMethod) {
629
- const violation = checkNewMethodViolation(file, method, mode);
632
+ const violation = checkNewMethodViolation(file, method, disableAllowed);
630
633
  if (violation) violations.push(violation);
631
634
  } else if (methodHasChanges(method, changedLineNumbers)) {
632
- violations.push(checkModifiedMethodViolation(file, method, mode));
635
+ const violation = checkModifiedMethodViolation(file, method, disableAllowed);
636
+ if (violation) violations.push(violation);
633
637
  }
634
638
  }
635
639
  }
@@ -673,44 +677,44 @@ function detectBase(workspaceRoot: string): string | null {
673
677
  * Report violations to console
674
678
  */
675
679
  // webpieces-disable max-lines-new-methods -- Error output formatting with multiple message sections
676
- function reportViolations(violations: MethodViolation[], maxLines: number, mode: ValidationMode): void {
680
+ function reportViolations(violations: MethodViolation[], limit: number, disableAllowed: boolean): void {
677
681
  console.error('');
678
- console.error(' Modified methods exceed ' + maxLines + ' lines!');
682
+ console.error('\u274c Modified methods exceed ' + limit + ' lines!');
679
683
  console.error('');
680
- console.error('📚 When you modify a method, you must bring it under ' + maxLines + ' lines.');
684
+ console.error('\ud83d\udcda When you modify a method, you must bring it under ' + limit + ' lines.');
681
685
  console.error(' This rule encourages GRADUAL cleanup so even though you did not cause it,');
682
686
  console.error(' you touched it, so you should fix now as part of your PR');
683
687
  console.error(' (this is for vibe coding and AI to fix as it touches things).');
684
688
  console.error(' You can refactor to stay under the limit 50% of the time. If not feasible, use the escape hatch.');
685
689
  console.error('');
686
690
  console.error(
687
- '⚠️ *** READ tmp/webpieces/webpieces.methodsize.md for detailed guidance on how to fix this easily *** ⚠️'
691
+ '\u26a0\ufe0f *** READ tmp/webpieces/webpieces.methodsize.md for detailed guidance on how to fix this easily *** \u26a0\ufe0f'
688
692
  );
689
693
  console.error('');
690
694
 
691
695
  for (const v of violations) {
692
696
  if (v.expiredDisable) {
693
- console.error(` ${v.file}:${v.line}`);
694
- console.error(` Method: ${v.methodName} (${v.lines} lines, max: ${maxLines})`);
695
- console.error(` EXPIRED DISABLE: Your disable comment dated ${v.expiredDate ?? 'unknown'} has expired (>1 month old).`);
697
+ console.error(` \u274c ${v.file}:${v.line}`);
698
+ console.error(` Method: ${v.methodName} (${v.lines} lines, max: ${limit})`);
699
+ console.error(` \u23f0 EXPIRED DISABLE: Your disable comment dated ${v.expiredDate ?? 'unknown'} has expired (>1 month old).`);
696
700
  console.error(` You must either FIX the method or UPDATE the date to get another month.`);
697
701
  } else {
698
- console.error(` ${v.file}:${v.line}`);
699
- console.error(` Method: ${v.methodName} (${v.lines} lines, max: ${maxLines})`);
702
+ console.error(` \u274c ${v.file}:${v.line}`);
703
+ console.error(` Method: ${v.methodName} (${v.lines} lines, max: ${limit})`);
700
704
  }
701
705
  }
702
706
  console.error('');
703
707
 
704
- // Only show escape hatch instructions when mode is not STRICT
705
- if (mode !== 'STRICT') {
708
+ // Only show escape hatch instructions when disableAllowed is true
709
+ if (disableAllowed) {
706
710
  console.error(' You can disable this error, but you will be forced to fix again in 1 month');
707
- console.error(' since 99% of methods can be less than ' + maxLines + ' lines of code.');
711
+ console.error(' since 99% of methods can be less than ' + limit + ' lines of code.');
708
712
  console.error('');
709
713
  console.error(' Use escape with DATE (expires in 1 month):');
710
714
  console.error(` // webpieces-disable max-lines-modified ${getTodayDateString()} -- [your reason]`);
711
715
  console.error('');
712
716
  } else {
713
- console.error(' ⚠️ validationMode is STRICT - disable comments are NOT allowed.');
717
+ console.error(' \u26a0\ufe0f disableAllowed is false - disable comments are NOT allowed.');
714
718
  console.error(' You MUST refactor to reduce method size.');
715
719
  console.error('');
716
720
  }
@@ -721,12 +725,13 @@ export default async function runExecutor(
721
725
  context: ExecutorContext
722
726
  ): Promise<ExecutorResult> {
723
727
  const workspaceRoot = context.root;
724
- const maxLines = options.max ?? 80;
725
- const mode: ValidationMode = options.mode ?? 'NORMAL';
728
+ const limit = options.limit ?? 80;
729
+ const mode: MethodMaxLimitMode = options.mode ?? 'NEW_AND_MODIFIED_METHODS';
730
+ const disableAllowed = options.disableAllowed ?? true;
726
731
 
727
732
  // Skip validation entirely if mode is OFF
728
733
  if (mode === 'OFF') {
729
- console.log('\n⏭️ Skipping modified method validation (validationMode: OFF)');
734
+ console.log('\n\u23ed\ufe0f Skipping modified method validation (mode: OFF)');
730
735
  console.log('');
731
736
  return { success: true };
732
737
  }
@@ -739,46 +744,47 @@ export default async function runExecutor(
739
744
  base = detectBase(workspaceRoot) ?? undefined;
740
745
 
741
746
  if (!base) {
742
- console.log('\n⏭️ Skipping modified method validation (could not detect base branch)');
747
+ console.log('\n\u23ed\ufe0f Skipping modified method validation (could not detect base branch)');
743
748
  console.log(' To run explicitly: nx affected --target=validate-modified-methods --base=origin/main');
744
749
  console.log('');
745
750
  return { success: true };
746
751
  }
747
752
 
748
- console.log('\n📏 Validating Modified Method Sizes (auto-detected base)\n');
753
+ console.log('\n\ud83d\udccf Validating Modified Method Sizes (auto-detected base)\n');
749
754
  } else {
750
- console.log('\n📏 Validating Modified Method Sizes\n');
755
+ console.log('\n\ud83d\udccf Validating Modified Method Sizes\n');
751
756
  }
752
757
 
753
758
  console.log(` Base: ${base}`);
754
759
  console.log(` Head: ${head ?? 'working tree (includes uncommitted changes)'}`);
755
- console.log(` Max lines for modified methods: ${maxLines}`);
756
- console.log(` Validation mode: ${mode}${mode === 'STRICT' ? ' (disable comments ignored)' : ''}`);
760
+ console.log(` Mode: ${mode}`);
761
+ console.log(` Limit for modified methods: ${limit}`);
762
+ console.log(` Disable allowed: ${disableAllowed}${!disableAllowed ? ' (no escape hatch)' : ''}`);
757
763
  console.log('');
758
764
 
759
765
  try {
760
766
  const changedFiles = getChangedTypeScriptFiles(workspaceRoot, base, head);
761
767
 
762
768
  if (changedFiles.length === 0) {
763
- console.log(' No TypeScript files changed');
769
+ console.log('\u2705 No TypeScript files changed');
764
770
  return { success: true };
765
771
  }
766
772
 
767
- console.log(`📂 Checking ${changedFiles.length} changed file(s)...`);
773
+ console.log(`\ud83d\udcc2 Checking ${changedFiles.length} changed file(s)...`);
768
774
 
769
- const violations = findViolations(workspaceRoot, changedFiles, base, maxLines, mode, head);
775
+ const violations = findViolations(workspaceRoot, changedFiles, base, limit, disableAllowed, head);
770
776
 
771
777
  if (violations.length === 0) {
772
- console.log(' All modified methods are under ' + maxLines + ' lines');
778
+ console.log('\u2705 All modified methods are under ' + limit + ' lines');
773
779
  return { success: true };
774
780
  }
775
781
 
776
782
  writeTmpInstructions(workspaceRoot);
777
- reportViolations(violations, maxLines, mode);
783
+ reportViolations(violations, limit, disableAllowed);
778
784
  return { success: false };
779
785
  } catch (err: unknown) {
780
786
  const error = err instanceof Error ? err : new Error(String(err));
781
- console.error(' Modified method validation failed:', error.message);
787
+ console.error('\u274c Modified method validation failed:', error.message);
782
788
  return { success: false };
783
789
  }
784
790
  }
@@ -4,16 +4,21 @@
4
4
  "description": "Validates that modified methods don't exceed a maximum line count. Encourages gradual cleanup of legacy long methods.",
5
5
  "type": "object",
6
6
  "properties": {
7
- "max": {
7
+ "limit": {
8
8
  "type": "number",
9
- "description": "Maximum number of lines allowed for modified methods",
9
+ "description": "Maximum lines allowed for modified methods",
10
10
  "default": 80
11
11
  },
12
12
  "mode": {
13
13
  "type": "string",
14
- "enum": ["STRICT", "NORMAL", "OFF"],
15
- "description": "STRICT: limits enforced, no disable comments. NORMAL: disable comments work. OFF: skip validation.",
16
- "default": "NORMAL"
14
+ "enum": ["OFF", "NEW_METHODS", "NEW_AND_MODIFIED_METHODS", "MODIFIED_FILES"],
15
+ "description": "OFF: skip validation. NEW_AND_MODIFIED_METHODS: new methods + methods with changes. MODIFIED_FILES: all methods in modified files.",
16
+ "default": "NEW_AND_MODIFIED_METHODS"
17
+ },
18
+ "disableAllowed": {
19
+ "type": "boolean",
20
+ "description": "Whether disable comments work. When false, no escape hatch (like old STRICT mode).",
21
+ "default": true
17
22
  }
18
23
  },
19
24
  "required": []
@@ -16,11 +16,11 @@
16
16
  * Escape hatch: Add webpieces-disable max-lines-new-methods comment with justification
17
17
  */
18
18
  import type { ExecutorContext } from '@nx/devkit';
19
- export type ValidationMode = 'STRICT' | 'NORMAL' | 'OFF';
19
+ export type MethodMaxLimitMode = 'OFF' | 'NEW_METHODS' | 'NEW_AND_MODIFIED_METHODS' | 'MODIFIED_FILES';
20
20
  export interface ValidateNewMethodsOptions {
21
- max?: number;
22
- strictMax?: number;
23
- mode?: ValidationMode;
21
+ limit?: number;
22
+ mode?: MethodMaxLimitMode;
23
+ disableAllowed?: boolean;
24
24
  }
25
25
  export interface ExecutorResult {
26
26
  success: boolean;
@@ -29,10 +29,8 @@ const METHODSIZE_DOC_CONTENT = `# Instructions: New Method Too Long
29
29
 
30
30
  ## Requirement
31
31
 
32
- **~50% of the time**, you can stay under the \`newMethodsMaxLines\` limit from nx.json
32
+ **~99% of the time**, you can stay under the \`limit\` from nx.json
33
33
  by extracting logical units into well-named methods.
34
-
35
- **~99% of the time**, you can stay under the \`modifiedAndNewMethodsMaxLines\` limit from nx.json.
36
34
  Nearly all software can be written with methods under this size.
37
35
 
38
36
  ## The "Table of Contents" Principle
@@ -270,8 +268,6 @@ function findNewMethodSignaturesInDiff(diffContent) {
270
268
  /**
271
269
  * Check if a line contains a webpieces-disable comment that exempts from new method validation.
272
270
  * Both max-lines-new-methods AND max-lines-modified are accepted here.
273
- * - max-lines-new-methods: Exempts from 30-line check, still checked by 80-line validator
274
- * - max-lines-modified: Exempts from both validators (ultimate escape hatch)
275
271
  */
276
272
  function hasDisableComment(lines, lineNumber) {
277
273
  // Check the line before the method (lineNumber is 1-indexed, array is 0-indexed)
@@ -284,7 +280,7 @@ function hasDisableComment(lines, lineNumber) {
284
280
  break;
285
281
  }
286
282
  if (line.includes('webpieces-disable')) {
287
- // Either escape hatch exempts from the 30-line new method check
283
+ // Either escape hatch exempts from the lowLimit new method check
288
284
  if (line.includes('max-lines-new-methods') || line.includes('max-lines-modified')) {
289
285
  return true;
290
286
  }
@@ -295,6 +291,7 @@ function hasDisableComment(lines, lineNumber) {
295
291
  /**
296
292
  * Parse a TypeScript file and find methods with their line counts
297
293
  */
294
+ // webpieces-disable max-lines-new-methods -- AST traversal requires inline visitor function
298
295
  function findMethodsInFile(filePath, workspaceRoot) {
299
296
  const fullPath = path.join(workspaceRoot, filePath);
300
297
  if (!fs.existsSync(fullPath))
@@ -347,7 +344,7 @@ function findMethodsInFile(filePath, workspaceRoot) {
347
344
  /**
348
345
  * Find new methods that exceed the line limit
349
346
  */
350
- function findViolations(workspaceRoot, changedFiles, base, maxLines, strictMaxLines, head) {
347
+ function findViolations(workspaceRoot, changedFiles, base, limit, disableAllowed, head) {
351
348
  const violations = [];
352
349
  for (const file of changedFiles) {
353
350
  // Get the diff to find which methods are NEW (not just modified)
@@ -360,29 +357,29 @@ function findViolations(workspaceRoot, changedFiles, base, maxLines, strictMaxLi
360
357
  for (const method of methods) {
361
358
  if (!newMethodNames.has(method.name))
362
359
  continue;
363
- // Check hard limit first (if defined) - NO escape possible
364
- if (strictMaxLines && method.lines > strictMaxLines) {
365
- violations.push({
366
- file,
367
- methodName: method.name,
368
- line: method.line,
369
- lines: method.lines,
370
- isNew: true,
371
- isHardLimit: true,
372
- limit: strictMaxLines,
373
- });
374
- }
375
- // Check soft limit - can be escaped with disable comment
376
- else if (method.lines > maxLines && !method.hasDisableComment) {
377
- violations.push({
378
- file,
379
- methodName: method.name,
380
- line: method.line,
381
- lines: method.lines,
382
- isNew: true,
383
- isHardLimit: false,
384
- limit: maxLines,
385
- });
360
+ if (method.lines > limit) {
361
+ if (!disableAllowed) {
362
+ // No escape possible
363
+ violations.push({
364
+ file,
365
+ methodName: method.name,
366
+ line: method.line,
367
+ lines: method.lines,
368
+ isNew: true,
369
+ limit,
370
+ });
371
+ }
372
+ else if (!method.hasDisableComment) {
373
+ // Escape allowed but not present
374
+ violations.push({
375
+ file,
376
+ methodName: method.name,
377
+ line: method.line,
378
+ lines: method.lines,
379
+ isNew: true,
380
+ limit,
381
+ });
382
+ }
386
383
  }
387
384
  }
388
385
  }
@@ -425,54 +422,43 @@ function detectBase(workspaceRoot) {
425
422
  /**
426
423
  * Report violations to the user with helpful instructions
427
424
  */
428
- // webpieces-disable max-lines-new-methods -- Console output formatting requires distinct sections for hard/soft violations
429
- function reportViolations(violations, maxLines, strictMaxLines) {
430
- const hardViolations = violations.filter((v) => v.isHardLimit);
431
- const softViolations = violations.filter((v) => !v.isHardLimit);
425
+ function reportViolations(violations, limit, disableAllowed) {
432
426
  console.error('');
433
- console.error(' New methods exceed line limits!');
427
+ console.error('\u274c New methods exceed ' + limit + ' line limit!');
434
428
  console.error('');
435
- console.error('📚 Methods should read like a "table of contents" - each method call');
436
- console.error(' describes a larger piece of work. You can refactor');
437
- console.error(' to stay under ' + maxLines + ' lines 50% of the time.');
429
+ console.error('\ud83d\udcda Methods should read like a "table of contents" - each method call');
430
+ console.error(' describes a larger piece of work.');
438
431
  console.error('');
439
- console.error('⚠️ *** READ tmp/webpieces/webpieces.methodsize.md for detailed guidance on how to fix this easily *** ⚠️');
432
+ console.error('\u26a0\ufe0f *** READ tmp/webpieces/webpieces.methodsize.md for detailed guidance on how to fix this easily *** \u26a0\ufe0f');
440
433
  console.error('');
441
- if (hardViolations.length > 0) {
442
- console.error('🚫 HARD LIMIT VIOLATIONS (cannot be bypassed with disable comment):');
443
- console.error('');
444
- for (const v of hardViolations) {
445
- console.error(` ❌ ${v.file}:${v.line}`);
446
- console.error(` Method: ${v.methodName} (${v.lines} lines, hard max: ${strictMaxLines})`);
447
- }
448
- console.error('');
449
- console.error(' These methods MUST be refactored - no escape hatch available.');
450
- console.error('');
434
+ if (disableAllowed) {
435
+ console.error('\u26a0\ufe0f VIOLATIONS (can use escape hatch):');
451
436
  }
452
- if (softViolations.length > 0) {
453
- console.error('⚠️ SOFT LIMIT VIOLATIONS (can be bypassed with disable comment):');
454
- console.error('');
455
- for (const v of softViolations) {
456
- console.error(` ❌ ${v.file}:${v.line}`);
457
- console.error(` Method: ${v.methodName} (${v.lines} lines, soft max: ${maxLines})`);
458
- }
459
- console.error('');
460
- console.error(' If you REALLY REALLY need more than ' + maxLines + ' lines, this happens 50% of the time,');
461
- console.error(' so use escape: // webpieces-disable max-lines-new-methods -- [your reason]');
462
- if (strictMaxLines) {
463
- console.error(` NOTE: Even with escape, you cannot exceed the hard limit of ${strictMaxLines} lines.`);
464
- }
465
- console.error('');
437
+ else {
438
+ console.error('\ud83d\udeab VIOLATIONS (cannot be bypassed with disable comment):');
439
+ }
440
+ console.error('');
441
+ for (const v of violations) {
442
+ console.error(` \u274c ${v.file}:${v.line}`);
443
+ console.error(` Method: ${v.methodName} (${v.lines} lines, limit: ${limit})`);
444
+ }
445
+ console.error('');
446
+ if (disableAllowed) {
447
+ console.error(' Use escape: // webpieces-disable max-lines-new-methods -- [your reason]');
466
448
  }
449
+ else {
450
+ console.error(' These methods MUST be refactored - no escape hatch available (disableAllowed=false).');
451
+ }
452
+ console.error('');
467
453
  }
468
454
  async function runExecutor(options, context) {
469
455
  const workspaceRoot = context.root;
470
- const maxLines = options.max ?? 30;
471
- const strictMaxLines = options.strictMax;
472
- const mode = options.mode ?? 'NORMAL';
456
+ const limit = options.limit ?? 80;
457
+ const mode = options.mode ?? 'NEW_AND_MODIFIED_METHODS';
458
+ const disableAllowed = options.disableAllowed ?? true;
473
459
  // Skip validation entirely if mode is OFF
474
460
  if (mode === 'OFF') {
475
- console.log('\n⏭️ Skipping new method validation (validationMode: OFF)');
461
+ console.log('\n\u23ed\ufe0f Skipping new method validation (mode: OFF)');
476
462
  console.log('');
477
463
  return { success: true };
478
464
  }
@@ -484,48 +470,43 @@ async function runExecutor(options, context) {
484
470
  // Try to auto-detect base from git merge-base
485
471
  base = detectBase(workspaceRoot) ?? undefined;
486
472
  if (!base) {
487
- console.log('\n⏭️ Skipping new method validation (could not detect base branch)');
473
+ console.log('\n\u23ed\ufe0f Skipping new method validation (could not detect base branch)');
488
474
  console.log(' To run explicitly: nx affected --target=validate-new-methods --base=origin/main');
489
475
  console.log('');
490
476
  return { success: true };
491
477
  }
492
- console.log('\n📏 Validating New Method Sizes (auto-detected base)\n');
478
+ console.log('\n\ud83d\udccf Validating New Method Sizes (auto-detected base)\n');
493
479
  }
494
480
  else {
495
- console.log('\n📏 Validating New Method Sizes\n');
481
+ console.log('\n\ud83d\udccf Validating New Method Sizes\n');
496
482
  }
497
483
  console.log(` Base: ${base}`);
498
484
  console.log(` Head: ${head ?? 'working tree (includes uncommitted changes)'}`);
499
- console.log(` Soft limit for new methods: ${maxLines} lines (can escape with disable comment)`);
500
- if (strictMaxLines) {
501
- console.log(` Hard limit for new methods: ${strictMaxLines} lines (NO escape possible)`);
502
- }
485
+ console.log(` Mode: ${mode}`);
486
+ console.log(` Limit for new methods: ${limit} lines (${disableAllowed ? 'can escape' : 'NO escape possible'})`);
503
487
  console.log('');
504
488
  try {
505
489
  // Get changed TypeScript files (base to head, or working tree if head not set)
506
490
  const changedFiles = getChangedTypeScriptFiles(workspaceRoot, base, head);
507
491
  if (changedFiles.length === 0) {
508
- console.log(' No TypeScript files changed');
492
+ console.log('\u2705 No TypeScript files changed');
509
493
  return { success: true };
510
494
  }
511
- console.log(`📂 Checking ${changedFiles.length} changed file(s)...`);
495
+ console.log(`\ud83d\udcc2 Checking ${changedFiles.length} changed file(s)...`);
512
496
  // Find violations
513
- const violations = findViolations(workspaceRoot, changedFiles, base, maxLines, strictMaxLines, head);
497
+ const violations = findViolations(workspaceRoot, changedFiles, base, limit, disableAllowed, head);
514
498
  if (violations.length === 0) {
515
- const limitMsg = strictMaxLines
516
- ? `soft limit (${maxLines}) or hard limit (${strictMaxLines})`
517
- : `${maxLines} lines`;
518
- console.log('✅ All new methods are within ' + limitMsg);
499
+ console.log('\u2705 All new methods are within ' + limit + ' lines');
519
500
  return { success: true };
520
501
  }
521
502
  // Write instructions file and report violations
522
503
  writeTmpInstructions(workspaceRoot);
523
- reportViolations(violations, maxLines, strictMaxLines);
504
+ reportViolations(violations, limit, disableAllowed);
524
505
  return { success: false };
525
506
  }
526
507
  catch (err) {
527
508
  const error = err instanceof Error ? err : new Error(String(err));
528
- console.error(' New method validation failed:', error.message);
509
+ console.error('\u274c New method validation failed:', error.message);
529
510
  return { success: false };
530
511
  }
531
512
  }