Agent skill
migration-lint
Comprehensive Angular migration compliance checker with auto-fix capabilities. Use when reviewing migrated code for DDD architecture, Angular 20 syntax, and UI pattern compliance.
Install this agent skill to your Project
npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/data/migration-lint
SKILL.md
Migration Lint Command
Review and fix migrated Angular code for compliance. This command reads ALL migration guidelines and performs a comprehensive checklist review.
Arguments
$ARGUMENTS- Target path to review (e.g.,libs/mxsecurity/connection-management-page)
Workflow
Step 1: Load ALL Migration Guidelines
IMPORTANT: Read the core SKILL.md first, then reference documents as needed from ``.
Core: one-ui-migration skill
| # | Topic | File | Category |
|---|---|---|---|
| 1 | Migration Context | rules/reference/migration-context.md | Foundation |
| 2 | Angular 20 Syntax | rules/reference/angular-20-syntax.md | Foundation |
| 3 | DDD Architecture | rules/reference/ddd-architecture.md | Architecture |
| 4 | State Management | rules/reference/state-management.md | Architecture |
| 5 | Authentication | rules/tools/auth.md | Architecture |
| 6 | Migration Checklist | rules/reference/migration-checklist.md | Foundation |
| 7 | Pitfalls Index | rules/reference/pitfalls/index.md | Pitfalls |
| 7a | Pitfalls: Translation & Layout | rules/reference/pitfalls/translation-layout.md | Pitfalls |
| 7b | Pitfalls: DDD Violations | rules/reference/pitfalls/ddd-violations.md | Pitfalls |
| 7c | Pitfalls: Angular Syntax | rules/reference/pitfalls/angular-syntax.md | Pitfalls |
| 7d | Pitfalls: Forms & Services | rules/reference/pitfalls/forms-services.md | Pitfalls |
| 8 | Validators | rules/tools/forms/validators.md | Forms |
| 9 | Error Handling | rules/tools/forms/error-handling.md | Forms |
| 10 | Form Patterns | rules/tools/forms/patterns.md | Forms |
| 11 | Page Layout | rules/tools/ui/page-layout.md | UI Patterns |
| 12a | Forms | rules/tools/ui/forms.md | UI Patterns |
| 12b | Buttons | rules/tools/ui/buttons.md | UI Patterns |
| 12c | Components | rules/tools/ui/components.md | UI Patterns |
| 13 | Dialogs | rules/tools/ui/dialogs.md | UI Patterns |
| 14 | Table Basics | rules/tools/tables/basics.md | Tables |
| 15 | Table Columns | rules/tools/tables/columns.md | Tables |
| 16 | Table Advanced | rules/tools/tables/advanced.md | Tables |
| 17 | API Type Definitions | rules/reference/api-types.md | API |
| 18 | Shared Stores | rules/reference/shared-stores.md | State |
Step 2: Read Target Files
Read all .ts, .html, and .scss files in the target path:
{target}/domain/src/lib/**/*.ts{target}/features/src/lib/**/*.ts{target}/features/src/lib/**/*.html{target}/features/src/lib/**/*.scss{target}/ui/src/lib/**/*.ts{target}/ui/src/lib/**/*.html{target}/ui/src/lib/**/*.scss{target}/shell/src/lib/**/*.ts
Step 3: Comprehensive Checklist Review
Check EVERY item from EVERY migration file:
Checklist by Category
Category 1: Foundation & Pitfalls
migration-context.md
- Project follows one-ui monorepo structure
- Uses correct scope tags (
scope:mxsecurity) - Library types match DDD pattern (
domain,features,ui,shell)
angular-syntax.md
- Uses
@ifinstead of*ngIf - Uses
@for (item of items; track item.id)instead of*ngFor - Uses
@switchinstead ofngSwitch - Uses
inject()instead of constructor injection - Uses
input()instead of@Input() - Uses
output()instead of@Output() - Uses
viewChild()/viewChildren()instead of@ViewChild()/@ViewChildren() - Uses
contentChild()/contentChildren()instead of@ContentChild()/@ContentChildren() - Uses
model()for two-way binding where appropriate - Components are standalone (default in Angular 20)
- Uses
ChangeDetectionStrategy.OnPush
migration-checklist.md
- Domain layer contains only business logic, models, services, state
- Features layer contains smart components with store injection
- UI layer contains presentational components with input/output ONLY (NO store injection)
- Shell layer contains routing configuration
- Barrel exports (
index.ts) are properly configured
pitfalls/translation-layout.md
- Translation keys match source exactly (no new keys created)
- Form layout matches source (row groupings preserved)
- No padding in page component styles
- Page uses
gl-page-contentclass (not ng-container) - Table toolbar button order: Refresh → Create/Delete (only if old code has refresh)
pitfalls/ddd-violations.md
- No form templates in features layer (extract to UI)
- No store injection in UI components
- Dialogs are in features layer (not UI)
- No business logic in features (move to domain)
- No HTTP calls in UI components
pitfalls/angular-syntax.md
- No mixing old/new control flow (
*ngIfwith@for) - All
@forloops havetrack - No NgModule patterns (use standalone)
-
langChanged()called at field level (not in computed) - Uses
inject()instead of constructor injection
pitfalls/forms-services.md
-
mutationMethod/queryMethodimported from@one-ui/mxsecurity/shared/domain(NOTshared/util) - No unnecessary
.def.tsfiles for constants - Uses
MxSnackbarService(notMatSnackBar) - Uses
controls.xxx(not.get('xxx')) - Form valueChanges uses
toSignal()in effects - Uses
EMPTY_DASHconstant (notutils.emptyDash) - Uses
oneUiNumberOnly(notappNumberOnly) - Uses
mx-password-inputfor password fields - Uses
mx-key-valuefor readonly displays - No
TRANSLOCO_SCOPEprovider (use global translation keys) - No endpoint constants (
#ENDPOINTS = {}) - inline URLs directly in API methods
Category 2: Architecture
ddd-architecture.md
- Domain layer has correct structure
- Features layer has correct structure
- UI layer has correct structure
- Shell layer has correct structure
- Dependencies flow correctly (UI → Domain, Features → UI/Domain)
- No UI components importing from features
- Shared domain utilities used where appropriate
state-management.md
- Uses NgRx SignalStore for state management
- Store follows correct naming convention (
XxxStore) - Uses
withEntities()for entity management - Uses
withRequestStatus()for loading states - Uses
withDataService()for API integration - Effects handle success/error properly
- Uses
patchState()correctly - Store is provided in correct scope
authentication.md
- Uses
AuthStorefor authentication state - Permission checks use correct patterns
- Protected routes have guards
- API calls include proper authentication headers
Category 3: Forms (forms/)
validators.md
- Uses
OneValidators.required(notValidators.required) - Uses
OneValidators.email(notValidators.email) - Uses
OneValidators.minLength(n)(notValidators.minLength) - Uses
OneValidators.maxLength(n)(notValidators.maxLength) - Uses
OneValidators.min(n)(notValidators.min) - Uses
OneValidators.max(n)(notValidators.max) - Uses
OneValidators.pattern(x)(notValidators.pattern) - Custom validators follow correct patterns
- Cross-field validators implemented correctly
- Import from
@one-ui/mxsecurity/shared/domain
error-handling.md
- Form errors displayed using
<mat-error> - Error messages use translation keys
- Async validators handle errors
- API errors displayed to user
- Uses
MxSnackbarServicefor notifications
patterns.md
- Uses
NonNullableFormBuilder(notFormBuilder) - Form controls accessed via
controls.xxx(not.get('xxx')) -
getRawValue()used for form submission - Dynamic forms use
FormArraycorrectly - Form reset/patch follows patterns
- Forms in UI layer use
input()/output()for data flow
Category 4: UI Patterns (ui/)
ui/page-layout.md
- Root wrapper has
class="gl-page-content" - Uses
<one-ui-breadcrumb />at top - Uses
<mx-page-title [title]="t('...')">for page title - Content wrapped in
class="content-wrapper"(NOTmat-card) - Uses
*transloco="let t"pattern - Section titles use
class="gl-title-md"
buttons.md
- Submit button uses
mat-flat-button color="primary" - Cancel button uses
mat-button - Toolbar buttons use
mat-stroked-button - NO
mat-raised-button(usemat-flat-button) - Loading state uses
[mxButtonIsLoading]directive - Disabled state properly handles
noPermission()
forms.md
- Single form field NOT wrapped in
<div class="form-row"> - Multiple fields on same row use
<div class="form-row">
dialogs.md
- Uses shared dialog config (
smallDialogConfig,mediumDialogConfig,largeDialogConfig) - Has
viewContainerRef: this.#viewContainerRefwhen dialog uses store -
ConfirmDialogComponentresult checked as boolean (NOTresult?.confirm) - Dialog data typed properly
- Dialog returns correct type
-
afterClosed()subscription cleaned up properly
Category 5: Tables (tables/)
basics.md
- Uses
<mx-table>component - Column definitions use
MxColumnDef[] - Has
data-testidattributes - Loading state shows skeleton
- Empty state handled properly
columns.md
- Column types match data
- Custom templates import
MatTableModuleandMatSortModule - Link columns use proper navigation
- Status columns use proper styling
- Action columns positioned correctly
advanced.md
- Selection implemented correctly (if applicable)
- Sorting configured properly
- Pagination implemented (if applicable)
- Filtering works correctly (if applicable)
- Toolbar buttons use
mat-stroked-button
Category 6: API & Services
api-types.md
- API types defined in domain layer
- Request/Response types properly typed
- Uses proper HTTP methods
- Error responses typed
- Enums defined for constants
- NO endpoint constants (
#ENDPOINTS = {...}) - inline URL strings directly in methods
shared-stores.md
- Uses shared stores where appropriate (e.g.,
TimeZoneStore) - Shared store initialization handled
- Cross-feature state accessed via shared stores
- No duplicate state management
Category 7: Additional Checks
Translation (Transloco)
- Uses
*transloco="let t"or@let t = translocoT - NO
translatepipe - Translation keys follow naming convention
- Parameters passed correctly to
t()
Directives
-
oneUiNumberOnly(notappNumberOnly) - Custom directives use
one-uiprefix
Services
-
MxSnackbarService(notMatSnackBar) - Snackbar:
snackBar.open(msg)(notsnackBar.open(msg, '', { duration: 3000 }))
Constants
-
EMPTY_DASHfrom@one-ui/mxsecurity/shared/domain(notutils.emptyDash)
Imports
- No circular imports
- Imports from correct library paths
- No relative imports crossing library boundaries
Password Fields
- Uses
<mx-password-input>for password fields
Readonly Display
- Uses
<mx-key-value>for readonly key-value displays
Step 4: Fix Issues
Auto-fix the following issues:
| Issue | Fix |
|---|---|
mat-raised-button |
→ mat-flat-button |
*ngIf |
→ @if |
*ngFor |
→ @for (item of items; track item.id) |
Validators.required |
→ OneValidators.required |
Validators.email |
→ OneValidators.email |
Validators.minLength(n) |
→ OneValidators.minLength(n) |
Validators.maxLength(n) |
→ OneValidators.maxLength(n) |
.get('xxx') |
→ controls.xxx |
class="section-title" |
→ class="gl-title-md" |
appNumberOnly |
→ oneUiNumberOnly |
this.utils.emptyDash |
→ EMPTY_DASH |
readonly #ENDPOINTS = { |
→ Remove constant, inline URLs directly in each method |
from '@one-ui/mxsecurity/shared/util' (for mutationMethod/queryMethod) |
→ from '@one-ui/mxsecurity/shared/domain' |
Step 5: Generate Report
Output a compliance report:
## Migration Lint Report
**Path:** {target_path}
**Date:** {current_date}
### Checklist Summary
| Category | Files Checked | Pass | Fail | N/A |
|----------|---------------|------|------|-----|
| Foundation (01, 02, 06) | 3 | Pass | Fail | - |
| Architecture (03, 04, 05) | 3 | Pass | Fail | - |
| Pitfalls (08, 08a, 08b, 08c, 08d) | 5 | Pass | Fail | - |
| Forms (09a, 09b, 09c) | 3 | Pass | Fail | - |
| UI Patterns (10a, 10b, 10c) | 3 | Pass | Fail | - |
| Tables (11a, 11b, 11c) | 3 | Pass | Fail | - |
| API & Services (12, 13) | 2 | Pass | Fail | - |
| **Total** | **22** | **X** | **Y** | **Z** |
### Issues Fixed
| File | Line | Issue | Fix Applied |
|------|------|-------|-------------|
| component.html | 15 | mat-raised-button | Changed to mat-flat-button |
### Issues Found (Manual Review Needed)
| File | Line | Issue | Recommendation | Guide Ref |
|------|------|-------|----------------|-----------|
| component.ts | 42 | Missing viewContainerRef | Add viewContainerRef to dialog config | dialogs.md |
| store.ts | 20 | Store in UI layer | Move to features layer | ddd-architecture.md |
### Detailed Checklist Results
#### migration-context.md (Pass)
- [x] Project follows one-ui monorepo structure
- [x] Uses correct scope tags
#### angular-syntax.md (Warning)
- [x] Uses @if instead of *ngIf
- [ ] Uses inject() instead of constructor injection (line 45)
... (continue for all files)
### Summary
- **Migration Files Checked:** 22/22
- **Auto-fixed:** X issues
- **Manual review needed:** Y issues
- **Passed checks:** Z items
- **Failed checks:** W items
Quick Reference
Button Types
<!-- Form submit button -->
<button mat-flat-button color="primary" type="submit">Apply</button>
<!-- Table toolbar button -->
<button mat-stroked-button>Create</button>
<!-- Cancel/secondary button -->
<button mat-button type="button">Cancel</button>
Page Layout
<div *transloco="let t" class="gl-page-content">
<one-ui-breadcrumb />
<mx-page-title [title]="t('page.title')" />
<div class="content-wrapper">
<!-- content here, NO mat-card -->
</div>
</div>
Form Row
<!-- Single field - NO form-row wrapper -->
<mat-form-field>
<mat-label>{{ t('label') }}</mat-label>
<input matInput formControlName="field" />
</mat-form-field>
<!-- Multiple fields on same row - USE form-row wrapper -->
<div class="form-row">
<mat-form-field>...</mat-form-field>
<mat-form-field>...</mat-form-field>
</div>
Dialog Config
import { mediumDialogConfig } from '@one-ui/mxsecurity/shared/domain';
this.#dialog.open(MyDialog, {
...mediumDialogConfig,
data: dialogData,
viewContainerRef: this.#viewContainerRef // Required if dialog uses store
});
Validators
import { OneValidators } from '@one-ui/mxsecurity/shared/domain';
this.#fb.group({
name: ['', [OneValidators.required, OneValidators.maxLength(32)]],
email: ['', [OneValidators.required, OneValidators.email]],
port: ['', [OneValidators.required, OneValidators.min(1), OneValidators.max(65535)]]
});
ConfirmDialogComponent
// ConfirmDialogComponent returns boolean, NOT { confirm: boolean }
const dialogRef = this.#dialog.open<ConfirmDialogComponent, ConfirmDialogData, boolean>(
ConfirmDialogComponent,
{
...mediumDialogConfig,
viewContainerRef: this.#viewContainerRef,
data: { title: '...', desc: '...' }
}
);
dialogRef.afterClosed().subscribe((result) => {
if (result) { // result is boolean
this.doSomething();
}
});
Snackbar Service
// Use MxSnackbarService instead of MatSnackBar
import { MxSnackbarService } from '@moxa/formoxa/mx-snackbar';
readonly #snackBar = inject(MxSnackbarService);
// Simple usage
this.#snackBar.open('Success message');
// Persistent message (no auto-dismiss)
this.#snackBar.open('Saving...', { duration: 0 });
Section Title
<!-- Use gl-title-md class (global style) -->
<h3 class="gl-title-md">{{ t('section.title') }}</h3>
<!-- NOT section-title (requires custom SCSS) -->
<h3 class="section-title">{{ t('section.title') }}</h3>
Form Controls Access
// .get() - no type safety
const value = this.form.get('username')?.value;
// controls.xxx - type safe
const value = this.form.controls.username.value;
// In ValidatorFn - use type assertion
#myValidator(): ValidatorFn {
return (formGroup: AbstractControl): null => {
const controls = (formGroup as typeof this.form).controls;
const fieldValue = controls.fieldName.value;
return null;
};
}
Password Input
<!-- Use mx-password-input for password fields -->
<mx-password-input
formControlName="password"
[maxlength]="32"
></mx-password-input>
Key-Value Display
<!-- Use mx-key-value for readonly displays -->
<mx-key-value [key]="t('label')" [value]="displayValue"></mx-key-value>
UI Component Pattern
// UI components use input()/output() ONLY - NO store injection
export class MyUiComponent {
readonly data = input<MyData>();
readonly isLoading = input<boolean>(false);
readonly save = output<MyData>();
readonly cancel = output<void>();
}
Features Component Pattern
// Features components can inject stores
export class MyFeatureComponent {
readonly #store = inject(MyStore);
readonly data = this.#store.data;
readonly isLoading = this.#store.isLoading;
}
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
Didn't find tool you were looking for?