@girardelli/architect 2.2.0 → 5.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/README.md +105 -116
- package/architect-run.sh +431 -0
- package/assets/banner-v3.html +561 -0
- package/dist/agent-generator/context-enricher.d.ts +58 -0
- package/dist/agent-generator/context-enricher.d.ts.map +1 -0
- package/dist/agent-generator/context-enricher.js +613 -0
- package/dist/agent-generator/context-enricher.js.map +1 -0
- package/dist/agent-generator/domain-inferrer.d.ts +52 -0
- package/dist/agent-generator/domain-inferrer.d.ts.map +1 -0
- package/dist/agent-generator/domain-inferrer.js +585 -0
- package/dist/agent-generator/domain-inferrer.js.map +1 -0
- package/dist/agent-generator/framework-detector.d.ts +40 -0
- package/dist/agent-generator/framework-detector.d.ts.map +1 -0
- package/dist/agent-generator/framework-detector.js +611 -0
- package/dist/agent-generator/framework-detector.js.map +1 -0
- package/dist/agent-generator/index.d.ts +47 -0
- package/dist/agent-generator/index.d.ts.map +1 -0
- package/dist/agent-generator/index.js +545 -0
- package/dist/agent-generator/index.js.map +1 -0
- package/dist/agent-generator/stack-detector.d.ts +14 -0
- package/dist/agent-generator/stack-detector.d.ts.map +1 -0
- package/dist/agent-generator/stack-detector.js +124 -0
- package/dist/agent-generator/stack-detector.js.map +1 -0
- package/dist/agent-generator/templates/core/agents.d.ts +17 -0
- package/dist/agent-generator/templates/core/agents.d.ts.map +1 -0
- package/dist/agent-generator/templates/core/agents.js +1256 -0
- package/dist/agent-generator/templates/core/agents.js.map +1 -0
- package/dist/agent-generator/templates/core/architecture-rules.d.ts +7 -0
- package/dist/agent-generator/templates/core/architecture-rules.d.ts.map +1 -0
- package/dist/agent-generator/templates/core/architecture-rules.js +274 -0
- package/dist/agent-generator/templates/core/architecture-rules.js.map +1 -0
- package/dist/agent-generator/templates/core/general-rules.d.ts +8 -0
- package/dist/agent-generator/templates/core/general-rules.d.ts.map +1 -0
- package/dist/agent-generator/templates/core/general-rules.js +301 -0
- package/dist/agent-generator/templates/core/general-rules.js.map +1 -0
- package/dist/agent-generator/templates/core/hooks-generator.d.ts +21 -0
- package/dist/agent-generator/templates/core/hooks-generator.d.ts.map +1 -0
- package/dist/agent-generator/templates/core/hooks-generator.js +233 -0
- package/dist/agent-generator/templates/core/hooks-generator.js.map +1 -0
- package/dist/agent-generator/templates/core/index-md.d.ts +7 -0
- package/dist/agent-generator/templates/core/index-md.d.ts.map +1 -0
- package/dist/agent-generator/templates/core/index-md.js +246 -0
- package/dist/agent-generator/templates/core/index-md.js.map +1 -0
- package/dist/agent-generator/templates/core/orchestrator.d.ts +8 -0
- package/dist/agent-generator/templates/core/orchestrator.d.ts.map +1 -0
- package/dist/agent-generator/templates/core/orchestrator.js +422 -0
- package/dist/agent-generator/templates/core/orchestrator.js.map +1 -0
- package/dist/agent-generator/templates/core/preflight.d.ts +8 -0
- package/dist/agent-generator/templates/core/preflight.d.ts.map +1 -0
- package/dist/agent-generator/templates/core/preflight.js +213 -0
- package/dist/agent-generator/templates/core/preflight.js.map +1 -0
- package/dist/agent-generator/templates/core/quality-gates.d.ts +11 -0
- package/dist/agent-generator/templates/core/quality-gates.d.ts.map +1 -0
- package/dist/agent-generator/templates/core/quality-gates.js +254 -0
- package/dist/agent-generator/templates/core/quality-gates.js.map +1 -0
- package/dist/agent-generator/templates/core/security-rules.d.ts +7 -0
- package/dist/agent-generator/templates/core/security-rules.d.ts.map +1 -0
- package/dist/agent-generator/templates/core/security-rules.js +528 -0
- package/dist/agent-generator/templates/core/security-rules.js.map +1 -0
- package/dist/agent-generator/templates/core/skills-generator.d.ts +19 -0
- package/dist/agent-generator/templates/core/skills-generator.d.ts.map +1 -0
- package/dist/agent-generator/templates/core/skills-generator.js +546 -0
- package/dist/agent-generator/templates/core/skills-generator.js.map +1 -0
- package/dist/agent-generator/templates/core/workflow-fix-bug.d.ts +7 -0
- package/dist/agent-generator/templates/core/workflow-fix-bug.d.ts.map +1 -0
- package/dist/agent-generator/templates/core/workflow-fix-bug.js +237 -0
- package/dist/agent-generator/templates/core/workflow-fix-bug.js.map +1 -0
- package/dist/agent-generator/templates/core/workflow-new-feature.d.ts +8 -0
- package/dist/agent-generator/templates/core/workflow-new-feature.d.ts.map +1 -0
- package/dist/agent-generator/templates/core/workflow-new-feature.js +321 -0
- package/dist/agent-generator/templates/core/workflow-new-feature.js.map +1 -0
- package/dist/agent-generator/templates/core/workflow-review.d.ts +7 -0
- package/dist/agent-generator/templates/core/workflow-review.d.ts.map +1 -0
- package/dist/agent-generator/templates/core/workflow-review.js +104 -0
- package/dist/agent-generator/templates/core/workflow-review.js.map +1 -0
- package/dist/agent-generator/templates/domain/index.d.ts +22 -0
- package/dist/agent-generator/templates/domain/index.d.ts.map +1 -0
- package/dist/agent-generator/templates/domain/index.js +1176 -0
- package/dist/agent-generator/templates/domain/index.js.map +1 -0
- package/dist/agent-generator/templates/stack/index.d.ts +8 -0
- package/dist/agent-generator/templates/stack/index.d.ts.map +1 -0
- package/dist/agent-generator/templates/stack/index.js +695 -0
- package/dist/agent-generator/templates/stack/index.js.map +1 -0
- package/dist/agent-generator/templates/template-helpers.d.ts +75 -0
- package/dist/agent-generator/templates/template-helpers.d.ts.map +1 -0
- package/dist/agent-generator/templates/template-helpers.js +726 -0
- package/dist/agent-generator/templates/template-helpers.js.map +1 -0
- package/dist/agent-generator/types.d.ts +196 -0
- package/dist/agent-generator/types.d.ts.map +1 -0
- package/dist/agent-generator/types.js +27 -0
- package/dist/agent-generator/types.js.map +1 -0
- package/dist/analyzer.d.ts +5 -0
- package/dist/analyzer.d.ts.map +1 -1
- package/dist/analyzer.js +46 -5
- package/dist/analyzer.js.map +1 -1
- package/dist/analyzers/forecast.d.ts +85 -0
- package/dist/analyzers/forecast.d.ts.map +1 -0
- package/dist/analyzers/forecast.js +337 -0
- package/dist/analyzers/forecast.js.map +1 -0
- package/dist/analyzers/git-cache.d.ts +7 -0
- package/dist/analyzers/git-cache.d.ts.map +1 -0
- package/dist/analyzers/git-cache.js +41 -0
- package/dist/analyzers/git-cache.js.map +1 -0
- package/dist/analyzers/git-history.d.ts +113 -0
- package/dist/analyzers/git-history.d.ts.map +1 -0
- package/dist/analyzers/git-history.js +333 -0
- package/dist/analyzers/git-history.js.map +1 -0
- package/dist/analyzers/index.d.ts +10 -0
- package/dist/analyzers/index.d.ts.map +1 -0
- package/dist/analyzers/index.js +7 -0
- package/dist/analyzers/index.js.map +1 -0
- package/dist/analyzers/temporal-scorer.d.ts +72 -0
- package/dist/analyzers/temporal-scorer.d.ts.map +1 -0
- package/dist/analyzers/temporal-scorer.js +140 -0
- package/dist/analyzers/temporal-scorer.js.map +1 -0
- package/dist/anti-patterns.d.ts +7 -0
- package/dist/anti-patterns.d.ts.map +1 -1
- package/dist/anti-patterns.js +25 -6
- package/dist/anti-patterns.js.map +1 -1
- package/dist/cli.d.ts +2 -3
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +275 -113
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +6 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +48 -11
- package/dist/config.js.map +1 -1
- package/dist/html-reporter.d.ts +3 -1
- package/dist/html-reporter.d.ts.map +1 -1
- package/dist/html-reporter.js +248 -12
- package/dist/html-reporter.js.map +1 -1
- package/dist/index.d.ts +16 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +63 -4
- package/dist/index.js.map +1 -1
- package/dist/project-summarizer.d.ts +38 -0
- package/dist/project-summarizer.d.ts.map +1 -0
- package/dist/project-summarizer.js +463 -0
- package/dist/project-summarizer.js.map +1 -0
- package/dist/refactor-reporter.js +1 -1
- package/dist/scanner.d.ts +8 -2
- package/dist/scanner.d.ts.map +1 -1
- package/dist/scanner.js +153 -113
- package/dist/scanner.js.map +1 -1
- package/dist/scorer.d.ts.map +1 -1
- package/dist/scorer.js +24 -11
- package/dist/scorer.js.map +1 -1
- package/dist/types.d.ts +29 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +12 -3
- package/src/agent-generator/context-enricher.ts +672 -0
- package/src/agent-generator/domain-inferrer.ts +635 -0
- package/src/agent-generator/framework-detector.ts +669 -0
- package/src/agent-generator/index.ts +634 -0
- package/src/agent-generator/stack-detector.ts +115 -0
- package/src/agent-generator/templates/core/agents.ts +1296 -0
- package/src/agent-generator/templates/core/architecture-rules.ts +287 -0
- package/src/agent-generator/templates/core/general-rules.ts +306 -0
- package/src/agent-generator/templates/core/hooks-generator.ts +242 -0
- package/src/agent-generator/templates/core/index-md.ts +260 -0
- package/src/agent-generator/templates/core/orchestrator.ts +459 -0
- package/src/agent-generator/templates/core/preflight.ts +215 -0
- package/src/agent-generator/templates/core/quality-gates.ts +256 -0
- package/src/agent-generator/templates/core/security-rules.ts +543 -0
- package/src/agent-generator/templates/core/skills-generator.ts +585 -0
- package/src/agent-generator/templates/core/workflow-fix-bug.ts +239 -0
- package/src/agent-generator/templates/core/workflow-new-feature.ts +323 -0
- package/src/agent-generator/templates/core/workflow-review.ts +106 -0
- package/src/agent-generator/templates/domain/index.ts +1201 -0
- package/src/agent-generator/templates/stack/index.ts +705 -0
- package/src/agent-generator/templates/template-helpers.ts +776 -0
- package/src/agent-generator/types.ts +232 -0
- package/src/analyzer.ts +51 -5
- package/src/analyzers/forecast.ts +496 -0
- package/src/analyzers/git-cache.ts +52 -0
- package/src/analyzers/git-history.ts +488 -0
- package/src/analyzers/index.ts +33 -0
- package/src/analyzers/temporal-scorer.ts +227 -0
- package/src/anti-patterns.ts +29 -6
- package/src/cli.ts +316 -117
- package/src/config.ts +52 -11
- package/src/html-reporter.ts +263 -13
- package/src/index.ts +93 -10
- package/src/project-summarizer.ts +521 -0
- package/src/refactor-reporter.ts +1 -1
- package/src/scanner.ts +136 -90
- package/src/scorer.ts +26 -11
- package/src/types.ts +27 -0
- package/tests/agent-generator.test.ts +427 -0
- package/tests/analyzers-integration.test.ts +174 -0
- package/tests/architect-adapter-enrichment.test.ts +9 -0
- package/tests/context-enricher.test.ts +971 -0
- package/tests/fixtures/monorepo/package.json +6 -0
- package/tests/fixtures/monorepo/packages/app/package.json +12 -0
- package/tests/fixtures/monorepo/packages/app/src/index.ts +6 -0
- package/tests/fixtures/monorepo/packages/core/package.json +7 -0
- package/tests/fixtures/monorepo/packages/core/src/index.ts +7 -0
- package/tests/forecast.test.ts +509 -0
- package/tests/framework-detector.test.ts +1172 -0
- package/tests/git-history.test.ts +254 -0
- package/tests/monorepo-scan.test.ts +170 -0
- package/tests/scanner.test.ts +7 -8
- package/tests/scorer.test.ts +594 -0
- package/tests/stack-detector.test.ts +241 -0
- package/tests/template-generation.test.ts +706 -0
- package/tests/template-helpers.test.ts +1152 -0
- package/tests/temporal-scorer.test.ts +307 -0
- package/dist/agent-generator.d.ts +0 -106
- package/dist/agent-generator.d.ts.map +0 -1
- package/dist/agent-generator.js +0 -1398
- package/dist/agent-generator.js.map +0 -1
- package/src/agent-generator.ts +0 -1526
|
@@ -0,0 +1,706 @@
|
|
|
1
|
+
import { TemplateContext, DEFAULT_AGENT_CONFIG, StackInfo } from '../src/agent-generator/types.js';
|
|
2
|
+
import { AnalysisReport, RefactoringPlan } from '../src/types.js';
|
|
3
|
+
|
|
4
|
+
// ── Core Templates ──
|
|
5
|
+
import { generateIndexMd } from '../src/agent-generator/templates/core/index-md.js';
|
|
6
|
+
import { generateOrchestrator } from '../src/agent-generator/templates/core/orchestrator.js';
|
|
7
|
+
import { generatePreflight } from '../src/agent-generator/templates/core/preflight.js';
|
|
8
|
+
import { generateQualityGates } from '../src/agent-generator/templates/core/quality-gates.js';
|
|
9
|
+
import { generateGeneralRules } from '../src/agent-generator/templates/core/general-rules.js';
|
|
10
|
+
import { generateArchitectureRules } from '../src/agent-generator/templates/core/architecture-rules.js';
|
|
11
|
+
import { generateSecurityRules } from '../src/agent-generator/templates/core/security-rules.js';
|
|
12
|
+
import { generateNewFeatureWorkflow } from '../src/agent-generator/templates/core/workflow-new-feature.js';
|
|
13
|
+
import { generateFixBugWorkflow } from '../src/agent-generator/templates/core/workflow-fix-bug.js';
|
|
14
|
+
import { generateReviewWorkflow } from '../src/agent-generator/templates/core/workflow-review.js';
|
|
15
|
+
import {
|
|
16
|
+
generateBackendAgent,
|
|
17
|
+
generateFrontendAgent,
|
|
18
|
+
generateSecurityAgent,
|
|
19
|
+
generateQAAgent,
|
|
20
|
+
generateTechDebtAgent,
|
|
21
|
+
generateCodeReviewChecklist,
|
|
22
|
+
generateDatabaseAgent,
|
|
23
|
+
generateMobileAgent,
|
|
24
|
+
} from '../src/agent-generator/templates/core/agents.js';
|
|
25
|
+
|
|
26
|
+
// ── Domain Templates ──
|
|
27
|
+
import {
|
|
28
|
+
generateC4Template,
|
|
29
|
+
generateBddTemplate,
|
|
30
|
+
generateTddTemplate,
|
|
31
|
+
generateAdrTemplate,
|
|
32
|
+
generateThreatModelTemplate,
|
|
33
|
+
} from '../src/agent-generator/templates/domain/index.js';
|
|
34
|
+
|
|
35
|
+
// ── Stack Templates ──
|
|
36
|
+
import { generateStackRules, getStackRuleFileName } from '../src/agent-generator/templates/stack/index.js';
|
|
37
|
+
|
|
38
|
+
// ── Helpers ──
|
|
39
|
+
|
|
40
|
+
function makeStack(overrides: Partial<StackInfo> = {}): StackInfo {
|
|
41
|
+
return {
|
|
42
|
+
primary: 'TypeScript',
|
|
43
|
+
languages: ['TypeScript'],
|
|
44
|
+
frameworks: ['NestJS'],
|
|
45
|
+
hasBackend: true,
|
|
46
|
+
hasFrontend: false,
|
|
47
|
+
hasMobile: false,
|
|
48
|
+
hasDatabase: true,
|
|
49
|
+
testFramework: 'Jest',
|
|
50
|
+
packageManager: 'npm',
|
|
51
|
+
...overrides,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function makeReport(overrides: Partial<AnalysisReport> = {}): AnalysisReport {
|
|
56
|
+
return {
|
|
57
|
+
timestamp: new Date().toISOString(),
|
|
58
|
+
projectInfo: {
|
|
59
|
+
path: '/test',
|
|
60
|
+
name: 'test-project',
|
|
61
|
+
frameworks: ['NestJS'],
|
|
62
|
+
totalFiles: 50,
|
|
63
|
+
totalLines: 5000,
|
|
64
|
+
primaryLanguages: ['TypeScript'],
|
|
65
|
+
},
|
|
66
|
+
score: {
|
|
67
|
+
overall: 72,
|
|
68
|
+
components: [],
|
|
69
|
+
breakdown: { modularity: 80, coupling: 65, cohesion: 70, layering: 75 },
|
|
70
|
+
},
|
|
71
|
+
antiPatterns: [
|
|
72
|
+
{
|
|
73
|
+
name: 'God Class',
|
|
74
|
+
severity: 'CRITICAL',
|
|
75
|
+
location: 'src/AppService.ts',
|
|
76
|
+
description: 'Class with 800 lines',
|
|
77
|
+
suggestion: 'Split into smaller services',
|
|
78
|
+
affectedFiles: ['src/AppService.ts'],
|
|
79
|
+
},
|
|
80
|
+
],
|
|
81
|
+
layers: [
|
|
82
|
+
{ name: 'API', files: ['src/controller.ts'], description: 'API layer' },
|
|
83
|
+
{ name: 'Service', files: ['src/service.ts'], description: 'Service layer' },
|
|
84
|
+
],
|
|
85
|
+
dependencyGraph: {
|
|
86
|
+
nodes: ['src/controller.ts', 'src/service.ts'],
|
|
87
|
+
edges: [{ from: 'src/controller.ts', to: 'src/service.ts', type: 'import', weight: 1 }],
|
|
88
|
+
},
|
|
89
|
+
suggestions: [],
|
|
90
|
+
diagram: { mermaid: '', type: 'layer' },
|
|
91
|
+
...overrides,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function makePlan(overrides: Partial<RefactoringPlan> = {}): RefactoringPlan {
|
|
96
|
+
return {
|
|
97
|
+
timestamp: new Date().toISOString(),
|
|
98
|
+
projectPath: '/test',
|
|
99
|
+
currentScore: {
|
|
100
|
+
overall: 72,
|
|
101
|
+
components: [],
|
|
102
|
+
breakdown: { modularity: 80, coupling: 65, cohesion: 70, layering: 75 },
|
|
103
|
+
},
|
|
104
|
+
estimatedScoreAfter: { overall: 82, breakdown: { modularity: 85, coupling: 75, cohesion: 80, layering: 80 } },
|
|
105
|
+
steps: [
|
|
106
|
+
{
|
|
107
|
+
id: 1,
|
|
108
|
+
tier: 1,
|
|
109
|
+
rule: 'hub-splitter',
|
|
110
|
+
priority: 'HIGH',
|
|
111
|
+
title: 'Split AppService',
|
|
112
|
+
description: 'Split into smaller services',
|
|
113
|
+
rationale: 'Reduce God Class',
|
|
114
|
+
operations: [],
|
|
115
|
+
scoreImpact: [{ metric: 'modularity', before: 80, after: 85 }],
|
|
116
|
+
},
|
|
117
|
+
],
|
|
118
|
+
totalOperations: 1,
|
|
119
|
+
tier1Steps: 1,
|
|
120
|
+
tier2Steps: 0,
|
|
121
|
+
...overrides,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function makeCtx(stackOverrides: Partial<StackInfo> = {}, reportOverrides: Partial<AnalysisReport> = {}): TemplateContext {
|
|
126
|
+
const stack = makeStack(stackOverrides);
|
|
127
|
+
const report = makeReport(reportOverrides);
|
|
128
|
+
const plan = makePlan();
|
|
129
|
+
return {
|
|
130
|
+
report,
|
|
131
|
+
plan,
|
|
132
|
+
stack,
|
|
133
|
+
projectName: 'test-project',
|
|
134
|
+
stackLabel: [...stack.languages, ...stack.frameworks].join(' + '),
|
|
135
|
+
config: DEFAULT_AGENT_CONFIG,
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// ──────────────────────────────────────────────────
|
|
140
|
+
|
|
141
|
+
describe('Core Templates', () => {
|
|
142
|
+
const ctx = makeCtx();
|
|
143
|
+
|
|
144
|
+
describe('INDEX.md', () => {
|
|
145
|
+
const output = generateIndexMd(ctx);
|
|
146
|
+
|
|
147
|
+
it('should contain header and project info', () => {
|
|
148
|
+
expect(output).toContain('Agent Framework');
|
|
149
|
+
expect(output).toContain('Architect v3.1');
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
it('should contain project name', () => {
|
|
153
|
+
expect(output).toContain('test-project');
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
it('should list mandatory reading order', () => {
|
|
157
|
+
expect(output).toContain('00-general');
|
|
158
|
+
expect(output).toContain('QUALITY-GATES');
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
it('should reference Architect plugin', () => {
|
|
162
|
+
expect(output).toMatch(/architect/i);
|
|
163
|
+
});
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
describe('ORCHESTRATOR', () => {
|
|
167
|
+
const output = generateOrchestrator(ctx);
|
|
168
|
+
|
|
169
|
+
it('should contain REGRA ABSOLUTA', () => {
|
|
170
|
+
expect(output).toContain('REGRA ABSOLUTA');
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
it('should contain approval gates', () => {
|
|
174
|
+
expect(output).toMatch(/gate|aprovação|approval/i);
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
it('should contain business questions', () => {
|
|
178
|
+
expect(output).toMatch(/Q\d/);
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
it('should be substantial (Enterprise-Grade)', () => {
|
|
182
|
+
expect(output.length).toBeGreaterThan(2000);
|
|
183
|
+
});
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
describe('PREFLIGHT', () => {
|
|
187
|
+
const output = generatePreflight(ctx);
|
|
188
|
+
|
|
189
|
+
it('should contain multiple phases', () => {
|
|
190
|
+
expect(output).toMatch(/Phase|Fase|FASE/);
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
it('should contain environment verification commands', () => {
|
|
194
|
+
expect(output).toMatch(/npm|npx|node/);
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
it('should contain red flags', () => {
|
|
198
|
+
expect(output).toMatch(/red flag|PARAR|STOP/i);
|
|
199
|
+
});
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
describe('QUALITY-GATES', () => {
|
|
203
|
+
const output = generateQualityGates(ctx);
|
|
204
|
+
|
|
205
|
+
it('should contain 3 gate levels', () => {
|
|
206
|
+
expect(output).toContain('CRITICAL');
|
|
207
|
+
expect(output).toContain('IMPORTANT');
|
|
208
|
+
expect(output).toContain('DESIRABLE');
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
it('should contain coverage threshold', () => {
|
|
212
|
+
expect(output).toContain(`${DEFAULT_AGENT_CONFIG.coverageMinimum}%`);
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
it('should contain blockers', () => {
|
|
216
|
+
expect(output).toContain('console.log');
|
|
217
|
+
});
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
describe('00-general', () => {
|
|
221
|
+
const output = generateGeneralRules(ctx);
|
|
222
|
+
|
|
223
|
+
it('should contain golden rules', () => {
|
|
224
|
+
expect(output).toContain('Regras de Ouro');
|
|
225
|
+
expect(output).toContain('Git Flow');
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
it('should contain naming conventions', () => {
|
|
229
|
+
expect(output).toMatch(/naming|convention|nomenclatura/i);
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
it('should contain forbidden actions', () => {
|
|
233
|
+
expect(output).toMatch(/proibid|forbidden/i);
|
|
234
|
+
});
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
describe('01-architecture', () => {
|
|
238
|
+
const output = generateArchitectureRules(ctx);
|
|
239
|
+
|
|
240
|
+
it('should contain layer rules table', () => {
|
|
241
|
+
expect(output).toContain('Camada');
|
|
242
|
+
expect(output).toContain('Responsabilidade');
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
it('should contain NestJS-specific patterns for NestJS stack', () => {
|
|
246
|
+
expect(output).toContain('NestJS');
|
|
247
|
+
expect(output).toContain('@Controller');
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
it('should contain dependency direction', () => {
|
|
251
|
+
expect(output).toContain('Direção de Dependência');
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
it('should contain anti-patterns section', () => {
|
|
255
|
+
expect(output).toContain('God Class');
|
|
256
|
+
expect(output).toContain('Circular');
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
it('should contain project anti-patterns from report', () => {
|
|
260
|
+
expect(output).toContain('AppService');
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
it('should contain architecture checklist', () => {
|
|
264
|
+
expect(output).toContain('Checklist');
|
|
265
|
+
});
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
describe('01-architecture (Python stack)', () => {
|
|
269
|
+
const pythonCtx = makeCtx({
|
|
270
|
+
primary: 'Python',
|
|
271
|
+
languages: ['Python'],
|
|
272
|
+
frameworks: ['Django'],
|
|
273
|
+
});
|
|
274
|
+
const output = generateArchitectureRules(pythonCtx);
|
|
275
|
+
|
|
276
|
+
it('should contain Python-specific layer rules', () => {
|
|
277
|
+
expect(output).toContain('Python');
|
|
278
|
+
expect(output).toContain('views.py');
|
|
279
|
+
});
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
describe('02-security', () => {
|
|
283
|
+
const output = generateSecurityRules(ctx);
|
|
284
|
+
|
|
285
|
+
it('should contain OWASP Top 10', () => {
|
|
286
|
+
expect(output).toContain('OWASP');
|
|
287
|
+
expect(output).toContain('A01');
|
|
288
|
+
expect(output).toContain('A10');
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
it('should contain REGRA ZERO', () => {
|
|
292
|
+
expect(output).toContain('REGRA ZERO');
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
it('should contain validation patterns', () => {
|
|
296
|
+
expect(output).toContain('Validação de Input');
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
it('should contain NestJS validation for NestJS stack', () => {
|
|
300
|
+
expect(output).toContain('class-validator');
|
|
301
|
+
expect(output).toContain('ValidationPipe');
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
it('should contain secrets management', () => {
|
|
305
|
+
expect(output).toContain('Secrets');
|
|
306
|
+
expect(output).toContain('.env');
|
|
307
|
+
expect(output).toContain('.gitignore');
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
it('should contain STRIDE', () => {
|
|
311
|
+
expect(output).toContain('STRIDE');
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
it('should contain security checklist per layer', () => {
|
|
315
|
+
expect(output).toContain('Controller');
|
|
316
|
+
expect(output).toContain('Service');
|
|
317
|
+
expect(output).toContain('Data');
|
|
318
|
+
});
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
describe('02-security (Python stack)', () => {
|
|
322
|
+
const pythonCtx = makeCtx({
|
|
323
|
+
primary: 'Python',
|
|
324
|
+
languages: ['Python'],
|
|
325
|
+
frameworks: ['FastAPI'],
|
|
326
|
+
});
|
|
327
|
+
const output = generateSecurityRules(pythonCtx);
|
|
328
|
+
|
|
329
|
+
it('should contain Python validation patterns', () => {
|
|
330
|
+
expect(output).toContain('Pydantic');
|
|
331
|
+
});
|
|
332
|
+
|
|
333
|
+
it('should contain Python audit commands', () => {
|
|
334
|
+
expect(output).toContain('pip audit');
|
|
335
|
+
});
|
|
336
|
+
});
|
|
337
|
+
});
|
|
338
|
+
|
|
339
|
+
describe('Workflow Templates', () => {
|
|
340
|
+
const ctx = makeCtx();
|
|
341
|
+
|
|
342
|
+
describe('new-feature', () => {
|
|
343
|
+
const output = generateNewFeatureWorkflow(ctx);
|
|
344
|
+
|
|
345
|
+
it('should contain 10 steps', () => {
|
|
346
|
+
// Check for step markers
|
|
347
|
+
const stepMatches = output.match(/step|passo|fase/gi);
|
|
348
|
+
expect(stepMatches).toBeTruthy();
|
|
349
|
+
expect(stepMatches!.length).toBeGreaterThan(5);
|
|
350
|
+
});
|
|
351
|
+
|
|
352
|
+
it('should contain approval gates', () => {
|
|
353
|
+
expect(output).toMatch(/aprov|gate|humano/i);
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
it('should contain integration document requirement', () => {
|
|
357
|
+
expect(output).toMatch(/integração|integration/i);
|
|
358
|
+
});
|
|
359
|
+
});
|
|
360
|
+
|
|
361
|
+
describe('fix-bug', () => {
|
|
362
|
+
const output = generateFixBugWorkflow(ctx);
|
|
363
|
+
|
|
364
|
+
it('should contain diagnostic approach', () => {
|
|
365
|
+
expect(output).toMatch(/diagnós|root cause|5 why/i);
|
|
366
|
+
});
|
|
367
|
+
|
|
368
|
+
it('should contain RED test requirement', () => {
|
|
369
|
+
expect(output).toMatch(/RED|teste.*falha/i);
|
|
370
|
+
});
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
describe('review', () => {
|
|
374
|
+
const output = generateReviewWorkflow(ctx);
|
|
375
|
+
|
|
376
|
+
it('should contain review dimensions', () => {
|
|
377
|
+
expect(output).toContain('Funcional');
|
|
378
|
+
expect(output).toMatch(/Qualidade|Quality/);
|
|
379
|
+
expect(output).toMatch(/Segurança|Security/);
|
|
380
|
+
});
|
|
381
|
+
});
|
|
382
|
+
});
|
|
383
|
+
|
|
384
|
+
describe('Agent Templates', () => {
|
|
385
|
+
const ctx = makeCtx();
|
|
386
|
+
|
|
387
|
+
describe('Backend Agent', () => {
|
|
388
|
+
const output = generateBackendAgent(ctx);
|
|
389
|
+
|
|
390
|
+
it('should reference the detected stack', () => {
|
|
391
|
+
expect(output).toContain('TypeScript');
|
|
392
|
+
});
|
|
393
|
+
|
|
394
|
+
it('should contain SOLID principles', () => {
|
|
395
|
+
expect(output).toContain('SOLID');
|
|
396
|
+
expect(output).toContain('Single Responsibility');
|
|
397
|
+
});
|
|
398
|
+
|
|
399
|
+
it('should require integration document', () => {
|
|
400
|
+
expect(output).toMatch(/integração|integration/i);
|
|
401
|
+
});
|
|
402
|
+
|
|
403
|
+
it('should contain coverage gate', () => {
|
|
404
|
+
expect(output).toContain(`${DEFAULT_AGENT_CONFIG.coverageMinimum}%`);
|
|
405
|
+
});
|
|
406
|
+
});
|
|
407
|
+
|
|
408
|
+
describe('Frontend Agent', () => {
|
|
409
|
+
const frontendCtx = makeCtx({
|
|
410
|
+
hasFrontend: true,
|
|
411
|
+
frameworks: ['Angular'],
|
|
412
|
+
});
|
|
413
|
+
const output = generateFrontendAgent(frontendCtx);
|
|
414
|
+
|
|
415
|
+
it('should require mockup approval', () => {
|
|
416
|
+
expect(output).toMatch(/mockup|MOCKUP/i);
|
|
417
|
+
});
|
|
418
|
+
|
|
419
|
+
it('should require all UI states', () => {
|
|
420
|
+
expect(output).toContain('loading');
|
|
421
|
+
expect(output).toContain('error');
|
|
422
|
+
expect(output).toContain('empty');
|
|
423
|
+
});
|
|
424
|
+
});
|
|
425
|
+
|
|
426
|
+
describe('Security Agent', () => {
|
|
427
|
+
const output = generateSecurityAgent(ctx);
|
|
428
|
+
|
|
429
|
+
it('should contain OWASP checklist', () => {
|
|
430
|
+
expect(output).toContain('OWASP');
|
|
431
|
+
});
|
|
432
|
+
});
|
|
433
|
+
|
|
434
|
+
describe('QA Agent', () => {
|
|
435
|
+
const output = generateQAAgent(ctx);
|
|
436
|
+
|
|
437
|
+
it('should contain coverage requirement', () => {
|
|
438
|
+
expect(output).toContain(`${DEFAULT_AGENT_CONFIG.coverageMinimum}%`);
|
|
439
|
+
});
|
|
440
|
+
|
|
441
|
+
it('should contain test pyramid', () => {
|
|
442
|
+
expect(output).toMatch(/pirâmide|pyramid/i);
|
|
443
|
+
});
|
|
444
|
+
|
|
445
|
+
it('should contain BDD/TDD process', () => {
|
|
446
|
+
expect(output).toContain('BDD');
|
|
447
|
+
expect(output).toContain('TDD');
|
|
448
|
+
});
|
|
449
|
+
});
|
|
450
|
+
|
|
451
|
+
describe('Tech Debt Agent', () => {
|
|
452
|
+
const output = generateTechDebtAgent(ctx);
|
|
453
|
+
|
|
454
|
+
it('should contain current score', () => {
|
|
455
|
+
expect(output).toContain('72/100');
|
|
456
|
+
});
|
|
457
|
+
|
|
458
|
+
it('should contain anti-patterns from report', () => {
|
|
459
|
+
expect(output).toContain('God Class');
|
|
460
|
+
});
|
|
461
|
+
|
|
462
|
+
it('should prevent score regression', () => {
|
|
463
|
+
expect(output).toMatch(/regre|NUNCA.*pode.*regredir/i);
|
|
464
|
+
});
|
|
465
|
+
});
|
|
466
|
+
|
|
467
|
+
describe('Database Agent', () => {
|
|
468
|
+
const output = generateDatabaseAgent(ctx);
|
|
469
|
+
|
|
470
|
+
it('should contain migration rules', () => {
|
|
471
|
+
expect(output).toMatch(/migration|migração/i);
|
|
472
|
+
});
|
|
473
|
+
|
|
474
|
+
it('should contain indexing rules', () => {
|
|
475
|
+
expect(output).toMatch(/índice|index/i);
|
|
476
|
+
});
|
|
477
|
+
});
|
|
478
|
+
|
|
479
|
+
describe('Mobile Agent', () => {
|
|
480
|
+
const mobileCtx = makeCtx({
|
|
481
|
+
primary: 'Dart',
|
|
482
|
+
languages: ['Dart'],
|
|
483
|
+
frameworks: ['Flutter'],
|
|
484
|
+
hasMobile: true,
|
|
485
|
+
});
|
|
486
|
+
const output = generateMobileAgent(mobileCtx);
|
|
487
|
+
|
|
488
|
+
it('should be Flutter-specific', () => {
|
|
489
|
+
expect(output).toContain('Flutter');
|
|
490
|
+
});
|
|
491
|
+
|
|
492
|
+
it('should require all states', () => {
|
|
493
|
+
expect(output).toContain('loading');
|
|
494
|
+
expect(output).toContain('error');
|
|
495
|
+
expect(output).toContain('empty');
|
|
496
|
+
});
|
|
497
|
+
});
|
|
498
|
+
|
|
499
|
+
describe('Code Review Checklist', () => {
|
|
500
|
+
const output = generateCodeReviewChecklist(ctx);
|
|
501
|
+
|
|
502
|
+
it('should contain mandatory section', () => {
|
|
503
|
+
expect(output).toContain('Obrigatório');
|
|
504
|
+
});
|
|
505
|
+
|
|
506
|
+
it('should contain security section', () => {
|
|
507
|
+
expect(output).toMatch(/Segurança|Security/);
|
|
508
|
+
});
|
|
509
|
+
});
|
|
510
|
+
});
|
|
511
|
+
|
|
512
|
+
describe('Domain Templates', () => {
|
|
513
|
+
it('C4 template should contain 4 levels', () => {
|
|
514
|
+
const output = generateC4Template();
|
|
515
|
+
expect(output).toContain('Contexto');
|
|
516
|
+
expect(output).toContain('Container');
|
|
517
|
+
expect(output).toContain('Componente');
|
|
518
|
+
expect(output).toContain('Código');
|
|
519
|
+
});
|
|
520
|
+
|
|
521
|
+
it('BDD template should contain Gherkin format', () => {
|
|
522
|
+
const output = generateBddTemplate();
|
|
523
|
+
expect(output).toMatch(/Given|Dado/i);
|
|
524
|
+
expect(output).toMatch(/When|Quando/i);
|
|
525
|
+
expect(output).toMatch(/Then|Então/i);
|
|
526
|
+
});
|
|
527
|
+
|
|
528
|
+
it('TDD template should contain RED-GREEN-REFACTOR', () => {
|
|
529
|
+
const output = generateTddTemplate();
|
|
530
|
+
expect(output).toContain('RED');
|
|
531
|
+
expect(output).toContain('GREEN');
|
|
532
|
+
expect(output).toContain('REFACTOR');
|
|
533
|
+
});
|
|
534
|
+
|
|
535
|
+
it('ADR template should contain decision record structure', () => {
|
|
536
|
+
const output = generateAdrTemplate();
|
|
537
|
+
expect(output).toMatch(/Status|Contexto|Context|Decision|Decisão/);
|
|
538
|
+
});
|
|
539
|
+
|
|
540
|
+
it('Threat Model template should contain STRIDE', () => {
|
|
541
|
+
const output = generateThreatModelTemplate();
|
|
542
|
+
expect(output).toContain('STRIDE');
|
|
543
|
+
expect(output).toContain('poofing'); // **S**poofing contains "poofing"
|
|
544
|
+
expect(output).toContain('ampering'); // **T**ampering
|
|
545
|
+
});
|
|
546
|
+
});
|
|
547
|
+
|
|
548
|
+
describe('Stack-Specific Templates', () => {
|
|
549
|
+
it('should generate NestJS rules for NestJS stack', () => {
|
|
550
|
+
const ctx = makeCtx({ frameworks: ['NestJS'] });
|
|
551
|
+
const output = generateStackRules(ctx);
|
|
552
|
+
|
|
553
|
+
expect(output).not.toBeNull();
|
|
554
|
+
expect(output).toContain('NestJS');
|
|
555
|
+
expect(output).toContain('@Module');
|
|
556
|
+
expect(output).toContain('@Controller');
|
|
557
|
+
expect(output).toContain('@Injectable');
|
|
558
|
+
});
|
|
559
|
+
|
|
560
|
+
it('should generate Angular rules for Angular stack', () => {
|
|
561
|
+
const ctx = makeCtx({ frameworks: ['Angular'], hasFrontend: true });
|
|
562
|
+
const output = generateStackRules(ctx);
|
|
563
|
+
|
|
564
|
+
expect(output).not.toBeNull();
|
|
565
|
+
expect(output).toContain('Angular');
|
|
566
|
+
expect(output).toContain('OnPush');
|
|
567
|
+
});
|
|
568
|
+
|
|
569
|
+
it('should generate Flutter rules for Flutter stack', () => {
|
|
570
|
+
const ctx = makeCtx({
|
|
571
|
+
primary: 'Dart',
|
|
572
|
+
languages: ['Dart'],
|
|
573
|
+
frameworks: ['Flutter'],
|
|
574
|
+
hasMobile: true,
|
|
575
|
+
});
|
|
576
|
+
const output = generateStackRules(ctx);
|
|
577
|
+
|
|
578
|
+
expect(output).not.toBeNull();
|
|
579
|
+
expect(output).toContain('Flutter');
|
|
580
|
+
expect(output).toContain('BLoC');
|
|
581
|
+
});
|
|
582
|
+
|
|
583
|
+
it('should generate Python rules for Django stack', () => {
|
|
584
|
+
const ctx = makeCtx({
|
|
585
|
+
primary: 'Python',
|
|
586
|
+
languages: ['Python'],
|
|
587
|
+
frameworks: ['Django'],
|
|
588
|
+
});
|
|
589
|
+
const output = generateStackRules(ctx);
|
|
590
|
+
|
|
591
|
+
expect(output).not.toBeNull();
|
|
592
|
+
expect(output).toContain('Django');
|
|
593
|
+
});
|
|
594
|
+
|
|
595
|
+
it('should generate Next.js rules for Next.js stack', () => {
|
|
596
|
+
const ctx = makeCtx({ frameworks: ['Next.js'], hasFrontend: true });
|
|
597
|
+
const output = generateStackRules(ctx);
|
|
598
|
+
|
|
599
|
+
expect(output).not.toBeNull();
|
|
600
|
+
expect(output).toContain('Next.js');
|
|
601
|
+
expect(output).toContain('Server Component');
|
|
602
|
+
});
|
|
603
|
+
|
|
604
|
+
it('should generate Spring rules for Spring stack', () => {
|
|
605
|
+
const ctx = makeCtx({
|
|
606
|
+
primary: 'Java/Kotlin',
|
|
607
|
+
languages: ['Java/Kotlin'],
|
|
608
|
+
frameworks: ['Spring'],
|
|
609
|
+
});
|
|
610
|
+
const output = generateStackRules(ctx);
|
|
611
|
+
|
|
612
|
+
expect(output).not.toBeNull();
|
|
613
|
+
expect(output).toContain('Spring');
|
|
614
|
+
});
|
|
615
|
+
|
|
616
|
+
it('should generate Express rules for Express stack', () => {
|
|
617
|
+
const ctx = makeCtx({ frameworks: ['Express'] });
|
|
618
|
+
const output = generateStackRules(ctx);
|
|
619
|
+
|
|
620
|
+
expect(output).not.toBeNull();
|
|
621
|
+
expect(output).toContain('Express');
|
|
622
|
+
});
|
|
623
|
+
|
|
624
|
+
it('should return null for stacks without specific rules', () => {
|
|
625
|
+
const ctx = makeCtx({ frameworks: [] });
|
|
626
|
+
const output = generateStackRules(ctx);
|
|
627
|
+
|
|
628
|
+
expect(output).toBeNull();
|
|
629
|
+
});
|
|
630
|
+
|
|
631
|
+
describe('getStackRuleFileName', () => {
|
|
632
|
+
it('should return 03-nestjs for NestJS', () => {
|
|
633
|
+
const ctx = makeCtx({ frameworks: ['NestJS'] });
|
|
634
|
+
expect(getStackRuleFileName(ctx)).toBe('03-nestjs');
|
|
635
|
+
});
|
|
636
|
+
|
|
637
|
+
it('should return 03-angular for Angular', () => {
|
|
638
|
+
const ctx = makeCtx({ frameworks: ['Angular'] });
|
|
639
|
+
expect(getStackRuleFileName(ctx)).toBe('03-angular');
|
|
640
|
+
});
|
|
641
|
+
|
|
642
|
+
it('should return 03-flutter for Flutter', () => {
|
|
643
|
+
const ctx = makeCtx({ frameworks: ['Flutter'] });
|
|
644
|
+
expect(getStackRuleFileName(ctx)).toBe('03-flutter');
|
|
645
|
+
});
|
|
646
|
+
|
|
647
|
+
it('should return null for no framework', () => {
|
|
648
|
+
const ctx = makeCtx({ frameworks: [] });
|
|
649
|
+
expect(getStackRuleFileName(ctx)).toBeNull();
|
|
650
|
+
});
|
|
651
|
+
});
|
|
652
|
+
});
|
|
653
|
+
|
|
654
|
+
describe('Template Quality (Enterprise-Grade)', () => {
|
|
655
|
+
const ctx = makeCtx();
|
|
656
|
+
|
|
657
|
+
it('core templates should be substantial (not skeleton)', () => {
|
|
658
|
+
const templates = [
|
|
659
|
+
{ name: 'INDEX.md', content: generateIndexMd(ctx) },
|
|
660
|
+
{ name: 'ORCHESTRATOR', content: generateOrchestrator(ctx) },
|
|
661
|
+
{ name: 'PREFLIGHT', content: generatePreflight(ctx) },
|
|
662
|
+
{ name: 'QUALITY-GATES', content: generateQualityGates(ctx) },
|
|
663
|
+
{ name: '00-general', content: generateGeneralRules(ctx) },
|
|
664
|
+
{ name: '01-architecture', content: generateArchitectureRules(ctx) },
|
|
665
|
+
{ name: '02-security', content: generateSecurityRules(ctx) },
|
|
666
|
+
{ name: 'new-feature', content: generateNewFeatureWorkflow(ctx) },
|
|
667
|
+
];
|
|
668
|
+
|
|
669
|
+
for (const t of templates) {
|
|
670
|
+
// Enterprise-Grade templates should be > 1500 chars minimum
|
|
671
|
+
expect(t.content.length).toBeGreaterThan(1500);
|
|
672
|
+
}
|
|
673
|
+
});
|
|
674
|
+
|
|
675
|
+
it('all templates should contain Architect v3.1 signature', () => {
|
|
676
|
+
const templates = [
|
|
677
|
+
generateOrchestrator(ctx),
|
|
678
|
+
generatePreflight(ctx),
|
|
679
|
+
generateQualityGates(ctx),
|
|
680
|
+
generateGeneralRules(ctx),
|
|
681
|
+
generateArchitectureRules(ctx),
|
|
682
|
+
generateSecurityRules(ctx),
|
|
683
|
+
generateBackendAgent(ctx),
|
|
684
|
+
generateSecurityAgent(ctx),
|
|
685
|
+
generateQAAgent(ctx),
|
|
686
|
+
];
|
|
687
|
+
|
|
688
|
+
for (const content of templates) {
|
|
689
|
+
expect(content).toContain('Architect v3.1');
|
|
690
|
+
}
|
|
691
|
+
});
|
|
692
|
+
|
|
693
|
+
it('all agent templates should contain agent_card or antigravity frontmatter', () => {
|
|
694
|
+
const agentTemplates = [
|
|
695
|
+
generateOrchestrator(ctx),
|
|
696
|
+
generateBackendAgent(ctx),
|
|
697
|
+
generateSecurityAgent(ctx),
|
|
698
|
+
generateQAAgent(ctx),
|
|
699
|
+
generateTechDebtAgent(ctx),
|
|
700
|
+
];
|
|
701
|
+
|
|
702
|
+
for (const content of agentTemplates) {
|
|
703
|
+
expect(content).toMatch(/antigravity:|agent_card:/);
|
|
704
|
+
}
|
|
705
|
+
});
|
|
706
|
+
});
|