Files
cursor_gen/flutter-cursor-templates/generator/src/resolver.dart
T
mansi.kansara 44b5d814d4 chore: bump cursor_templates_version to 1.0.4 and update related files
- Updated cursor_templates_version in project-brief.yaml to 1.0.4 for reproducibility.
- Enhanced CHANGELOG with fixes and features for version 1.0.4, including improved template resolution for global installs.
- Updated pubspec.yaml and VERSION file to reflect the new version.
- Added new templates for AGENTS.md and lefthook.yaml to the generator.
- Adjusted tests to include new root-level files in the output.

This release addresses template resolution issues and introduces new repo-level configuration files.
2026-05-14 12:25:13 +05:30

136 lines
6.5 KiB
Dart

// resolver.dart — Maps brief values → template file paths (Pillar 3, 4 improvements)
import 'models.dart';
class Resolver {
/// Returns an ordered list of template file keys to render.
/// Each key maps to: templates/<key>.mdc.tmpl (or SKILL.md.tmpl for skills)
static List<String> resolve(ProjectBrief brief) {
final files = <String>[];
// ── Universal (every project) ──────────────────────────────────────
files.addAll([
'rules/universal/flutter-core',
'rules/universal/ui-ux-standards',
'rules/universal/project-context',
]);
// ── Security (Pillar 5: always-on, not just for large/auth projects) ──
files.add('rules/security/security-standards');
// ── Error handling (always-on) ────────────────────────────────────
files.add('rules/error-handling/error-handling');
// ── State management — exactly one ───────────────────────────────
files.add('rules/state-management/${brief.stateManagement}');
// ── Architecture — exactly one ────────────────────────────────────
files.add('rules/architecture/${brief.architecture}');
// ── Backend — one or more ─────────────────────────────────────────
for (final b in brief.backends) files.add('rules/backend/$b');
if (brief.specialFeatures.contains('realtime')) {
files.add('rules/backend/realtime');
}
// ── Routing — exactly one ─────────────────────────────────────────
files.add('rules/routing/${brief.routing}');
// ── Testing — SM-matched ──────────────────────────────────────────
files.add('rules/testing/testing-${brief.stateManagement}');
if (brief.testingDepth == 'full' || brief.testingDepth == 'e2e') {
files.add('rules/testing/testing-e2e-${brief.e2eTool}');
}
// ── Platform targets (Pillar 4) ───────────────────────────────────
for (final platform in brief.platforms) {
files.add('rules/platform/platform-$platform');
}
// ── Code generation tools (Pillar 4) ─────────────────────────────
for (final tool in brief.codegenTools) {
files.add('rules/codegen/codegen-$tool');
}
// ── Hooks (Pillar 4) — tied to codegen, not state_management ─────
if (brief.codegenTools.isNotEmpty) {
files.addAll([
'hooks/hooks-json',
'hooks/flutter-analyze',
'hooks/grind-tests',
'hooks/arch-guard',
]);
}
// ── Localization ──────────────────────────────────────────────────
if (brief.i18nEnabled) {
files.add('rules/i18n/localization');
}
// ── Skills ────────────────────────────────────────────────────────
files.addAll([
'skills/scaffold-feature',
'skills/scaffold-screen',
'skills/generate-tests',
'skills/build',
]);
if (brief.apiDocsFormat != 'none') files.add('skills/generate-api-client');
if (brief.flavors.length > 1) files.add('skills/create-flavor');
if (brief.cicd.isNotEmpty) files.add('skills/deploy');
// ── Agents ────────────────────────────────────────────────────────
files.addAll([
'agents/code-reviewer',
'agents/test-writer',
'agents/ui-validator',
]);
if (brief.backends.contains('rest')) files.add('agents/api-client-gen');
// Pillar 5: Security agent as ADDITIONAL layer (rules are primary)
if (brief.scale == 'large' || brief.auth != 'none') {
files.add('agents/security-agent');
}
if (brief.stateManagement == 'getx') {
files.add('agents/migration-agent');
}
files.addAll(['root/AGENTS.md', 'root/lefthook.yaml']);
return files;
}
/// Returns human-readable description of why each file was included
static Map<String, String> resolveWithReasons(ProjectBrief brief) {
final resolved = resolve(brief);
final reasons = <String, String>{};
for (final f in resolved) {
reasons[f] = _reason(f, brief);
}
return reasons;
}
static String _reason(String key, ProjectBrief brief) {
if (key.contains('universal')) return 'Always included';
if (key.contains('security')) return 'Always included — Pillar 5';
if (key.contains('error-handling')) return 'Always included';
if (key.contains('state-management')) return 'Matches stack.state_management: ${brief.stateManagement}';
if (key.contains('architecture')) return 'Matches stack.architecture: ${brief.architecture}';
if (key.contains('routing')) return 'Matches stack.routing: ${brief.routing}';
if (key.contains('testing-e2e')) return 'testing.depth includes e2e';
if (key.contains('testing')) return 'Matches state_management testing patterns';
if (key.contains('platform')) return 'Matches stack.platforms';
if (key.startsWith('hooks/')) {
return 'stack.codegen non-empty — Cursor hooks for analyze, boundaries, and tests';
}
if (key.contains('codegen')) return 'Matches stack.codegen';
if (key.contains('i18n')) return 'localization.enabled: true';
if (key.contains('migration')) return 'state_management is GetX — migration guidance included';
if (key.contains('security-agent')) return 'scale: ${brief.scale} or auth is configured';
if (key == 'skills/build') return 'Always included — universal TDD-first feature implementation command';
if (key.contains('api-client')) return 'api_docs.format is set';
if (key.contains('realtime')) return 'features.special contains realtime';
if (key.startsWith('root/')) return 'Repo-level companion files';
return 'Included';
}
}