fraim-framework 2.0.52 → 2.0.55
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/registry/scripts/profile-server.js +2 -1
- package/dist/src/ai-manager/ai-manager.js +49 -1
- package/dist/src/ai-manager/phase-flow.js +68 -0
- package/dist/src/utils/digest-utils.js +18 -7
- package/dist/tests/test-debug-session.js +6 -2
- package/dist/tests/test-enhanced-session-init.js +6 -2
- package/dist/tests/test-mcp-lifecycle-methods.js +1 -2
- package/dist/tests/test-mcp-template-processing.js +6 -2
- package/dist/tests/test-modular-issue-tracking.js +6 -2
- package/dist/tests/test-node-compatibility.js +4 -2
- package/dist/tests/test-npm-install.js +4 -2
- package/dist/tests/test-productivity-integration.js +157 -0
- package/dist/tests/test-session-rehydration.js +1 -2
- package/dist/tests/test-telemetry.js +1 -2
- package/dist/tests/test-users-to-target-workflow.js +253 -0
- package/index.js +44 -55
- package/package.json +5 -5
- package/registry/agent-guardrails.md +62 -62
- package/registry/scripts/detect-tautological-tests.sh +38 -38
- package/registry/scripts/productivity/build-productivity-csv.mjs +242 -0
- package/registry/scripts/productivity/fetch-pr-details.mjs +144 -0
- package/registry/scripts/productivity/productivity-report.sh +147 -0
- package/registry/scripts/profile-server.ts +1 -1
- package/registry/scripts/validate-openapi-limits.ts +366 -366
- package/registry/scripts/validate-test-coverage.ts +280 -280
- package/registry/stubs/workflows/customer-development/ai-coach-phases/phase1-customer-profiling.md +11 -0
- package/registry/stubs/workflows/customer-development/ai-coach-phases/phase1-survey-scoping.md +11 -0
- package/registry/stubs/workflows/customer-development/ai-coach-phases/phase2-platform-discovery.md +11 -0
- package/registry/stubs/workflows/customer-development/ai-coach-phases/phase2-survey-build-linkedin.md +11 -0
- package/registry/stubs/workflows/customer-development/ai-coach-phases/phase3-prospect-qualification.md +11 -0
- package/registry/stubs/workflows/customer-development/ai-coach-phases/phase3-survey-build-reddit.md +11 -0
- package/registry/stubs/workflows/customer-development/ai-coach-phases/phase4-inventory-compilation.md +11 -0
- package/registry/stubs/workflows/customer-development/ai-coach-phases/phase4-survey-build-x.md +11 -0
- package/registry/stubs/workflows/customer-development/ai-coach-phases/phase5-survey-build-facebook.md +11 -0
- package/registry/stubs/workflows/customer-development/ai-coach-phases/phase6-survey-build-custom.md +11 -0
- package/registry/stubs/workflows/customer-development/ai-coach-phases/phase7-survey-dispatch.md +11 -0
- package/registry/stubs/workflows/customer-development/templates/customer-persona-template.md +11 -0
- package/registry/stubs/workflows/customer-development/templates/search-strategy-template.md +11 -0
- package/registry/stubs/workflows/customer-development/user-survey-dispatch.md +11 -0
- package/registry/stubs/workflows/customer-development/users-to-target.md +11 -0
- package/registry/stubs/workflows/productivity-report/productivity-report.md +11 -0
- package/bin/fraim.js +0 -8
- package/dist/registry/ai-manager-rules/design-phases/design.md +0 -108
- package/dist/registry/ai-manager-rules/design-phases/finalize.md +0 -60
- package/dist/registry/ai-manager-rules/design-phases/validate.md +0 -125
- package/dist/registry/ai-manager-rules/design.json +0 -97
- package/dist/registry/ai-manager-rules/implement-phases/code.md +0 -323
- package/dist/registry/ai-manager-rules/implement-phases/completeness-review.md +0 -94
- package/dist/registry/ai-manager-rules/implement-phases/finalize.md +0 -177
- package/dist/registry/ai-manager-rules/implement-phases/quality-review.md +0 -304
- package/dist/registry/ai-manager-rules/implement-phases/regression.md +0 -159
- package/dist/registry/ai-manager-rules/implement-phases/repro.md +0 -101
- package/dist/registry/ai-manager-rules/implement-phases/scoping.md +0 -93
- package/dist/registry/ai-manager-rules/implement-phases/smoke.md +0 -225
- package/dist/registry/ai-manager-rules/implement-phases/spike.md +0 -118
- package/dist/registry/ai-manager-rules/implement-phases/validate.md +0 -347
- package/dist/registry/ai-manager-rules/implement.json +0 -153
- package/dist/registry/ai-manager-rules/shared-phases/finalize.md +0 -169
- package/dist/registry/ai-manager-rules/spec-phases/finalize.md +0 -60
- package/dist/registry/ai-manager-rules/spec-phases/spec.md +0 -102
- package/dist/registry/ai-manager-rules/spec-phases/validate.md +0 -118
- package/dist/registry/ai-manager-rules/spec.json +0 -112
- package/dist/registry/ai-manager-rules/test.json +0 -98
- package/dist/registry/scripts/build-scripts-generator.js +0 -205
- package/dist/registry/scripts/fraim-config.js +0 -61
- package/dist/registry/scripts/generic-issues-api.js +0 -100
- package/dist/registry/scripts/openapi-generator.js +0 -664
- package/dist/registry/scripts/performance/profile-server.js +0 -390
- package/dist/src/ai-manager/evidence-validator.js +0 -309
- package/dist/src/fraim/issue-tracking/ado-provider.js +0 -304
- package/dist/src/fraim/issue-tracking/factory.js +0 -63
- package/dist/src/fraim/issue-tracking/github-provider.js +0 -200
- package/dist/src/fraim/issue-tracking/types.js +0 -7
- package/dist/src/fraim/issue-tracking-config.js +0 -83
- package/dist/src/static-website-middleware.js +0 -75
- package/dist/test-utils.js +0 -96
- package/dist/tests/esm-compat.js +0 -11
- package/dist/tests/test-ai-manager-phase-protocol.js +0 -147
- package/dist/tests/test-ai-manager.js +0 -118
- package/dist/tests/test-chalk-esm-issue.js +0 -159
- package/dist/tests/test-chalk-real-world.js +0 -265
- package/dist/tests/test-chalk-regression.js +0 -377
- package/dist/tests/test-chalk-resolution-issue.js +0 -304
- package/dist/tests/test-evidence-validation.js +0 -221
- package/dist/tests/test-first-run-interactive.js +0 -1
- package/dist/tests/test-fraim-install-chalk-issue.js +0 -254
- package/dist/tests/test-markdown-to-pdf.js +0 -454
- package/dist/tests/test-npm-resolution-diagnostic.js +0 -140
- package/dist/tests/test-pr-review-integration.js +0 -1
- package/dist/website/.nojekyll +0 -0
- package/dist/website/404.html +0 -101
- package/dist/website/CNAME +0 -1
- package/dist/website/README.md +0 -22
- package/dist/website/demo.html +0 -604
- package/dist/website/images/.gitkeep +0 -1
- package/dist/website/images/fraim-logo.png +0 -0
- package/dist/website/index.html +0 -290
- package/dist/website/pricing.html +0 -414
- package/dist/website/script.js +0 -55
- package/dist/website/styles.css +0 -2647
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Comprehensive tests for Users to Target workflow
|
|
4
|
+
* Tests the complete customer discovery workflow including:
|
|
5
|
+
* - Phase loading and validation
|
|
6
|
+
* - Template file accessibility
|
|
7
|
+
* - AI coach phase content validation
|
|
8
|
+
* - Output directory structure
|
|
9
|
+
* - CSV template format validation
|
|
10
|
+
* - Browser automation integration points
|
|
11
|
+
*/
|
|
12
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
13
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
14
|
+
};
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
const node_test_1 = require("node:test");
|
|
17
|
+
const node_assert_1 = __importDefault(require("node:assert"));
|
|
18
|
+
const fs_1 = require("fs");
|
|
19
|
+
const path_1 = require("path");
|
|
20
|
+
(0, node_test_1.describe)('Users to Target Workflow', () => {
|
|
21
|
+
const workflowPath = 'registry/workflows/customer-development';
|
|
22
|
+
const mainWorkflowFile = (0, path_1.join)(workflowPath, 'users-to-target.md');
|
|
23
|
+
const templatesPath = (0, path_1.join)(workflowPath, 'templates');
|
|
24
|
+
const aiCoachPhasesPath = (0, path_1.join)(workflowPath, 'ai-coach-phases');
|
|
25
|
+
const outputPath = 'docs/customer-development';
|
|
26
|
+
(0, node_test_1.describe)('Workflow Structure', () => {
|
|
27
|
+
(0, node_test_1.it)('should have main workflow file', () => {
|
|
28
|
+
(0, node_assert_1.default)((0, fs_1.existsSync)(mainWorkflowFile), 'Main workflow file should exist');
|
|
29
|
+
const content = (0, fs_1.readFileSync)(mainWorkflowFile, 'utf-8');
|
|
30
|
+
(0, node_assert_1.default)(content.includes('# FRAIM Workflow: users-to-target'), 'Should have proper workflow header');
|
|
31
|
+
(0, node_assert_1.default)(content.includes('## Intent'), 'Should have intent section');
|
|
32
|
+
(0, node_assert_1.default)(content.includes('## Phases'), 'Should have phases section');
|
|
33
|
+
(0, node_assert_1.default)(content.includes('Phase 1: Customer Profiling'), 'Should include Phase 1');
|
|
34
|
+
(0, node_assert_1.default)(content.includes('Phase 2: Multi-Platform Discovery'), 'Should include Phase 2');
|
|
35
|
+
(0, node_assert_1.default)(content.includes('Phase 3: Prospect Qualification'), 'Should include Phase 3');
|
|
36
|
+
(0, node_assert_1.default)(content.includes('Phase 4: Inventory Compilation'), 'Should include Phase 4');
|
|
37
|
+
});
|
|
38
|
+
(0, node_test_1.it)('should have all required template files', () => {
|
|
39
|
+
const requiredTemplates = [
|
|
40
|
+
'customer-persona-template.md',
|
|
41
|
+
'search-strategy-template.md',
|
|
42
|
+
'prospect-inventory-template.csv'
|
|
43
|
+
];
|
|
44
|
+
requiredTemplates.forEach(template => {
|
|
45
|
+
const templatePath = (0, path_1.join)(templatesPath, template);
|
|
46
|
+
(0, node_assert_1.default)((0, fs_1.existsSync)(templatePath), `Template ${template} should exist`);
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
(0, node_test_1.it)('should have all AI coach phase files', () => {
|
|
50
|
+
const requiredPhases = [
|
|
51
|
+
'phase1-customer-profiling.md',
|
|
52
|
+
'phase2-platform-discovery.md',
|
|
53
|
+
'phase3-prospect-qualification.md',
|
|
54
|
+
'phase4-inventory-compilation.md'
|
|
55
|
+
];
|
|
56
|
+
requiredPhases.forEach(phase => {
|
|
57
|
+
const phasePath = (0, path_1.join)(aiCoachPhasesPath, phase);
|
|
58
|
+
(0, node_assert_1.default)((0, fs_1.existsSync)(phasePath), `Phase file ${phase} should exist`);
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
(0, node_test_1.describe)('Template Content Validation', () => {
|
|
63
|
+
(0, node_test_1.it)('should have properly structured customer persona template', () => {
|
|
64
|
+
const templatePath = (0, path_1.join)(templatesPath, 'customer-persona-template.md');
|
|
65
|
+
const content = (0, fs_1.readFileSync)(templatePath, 'utf-8');
|
|
66
|
+
// Check required sections
|
|
67
|
+
(0, node_assert_1.default)(content.includes('## Basic Information'), 'Should have Basic Information section');
|
|
68
|
+
(0, node_assert_1.default)(content.includes('## Demographics'), 'Should have Demographics section');
|
|
69
|
+
(0, node_assert_1.default)(content.includes('## Pain Points & Challenges'), 'Should have Pain Points section');
|
|
70
|
+
(0, node_assert_1.default)(content.includes('## Search Keywords'), 'Should have Search Keywords section');
|
|
71
|
+
(0, node_assert_1.default)(content.includes('### LinkedIn Keywords'), 'Should have LinkedIn keywords section');
|
|
72
|
+
(0, node_assert_1.default)(content.includes('### Reddit Keywords'), 'Should have Reddit keywords section');
|
|
73
|
+
(0, node_assert_1.default)(content.includes('### X (Twitter) Keywords'), 'Should have Twitter keywords section');
|
|
74
|
+
(0, node_assert_1.default)(content.includes('## Qualification Criteria'), 'Should have qualification criteria');
|
|
75
|
+
});
|
|
76
|
+
(0, node_test_1.it)('should have properly structured search strategy template', () => {
|
|
77
|
+
const templatePath = (0, path_1.join)(templatesPath, 'search-strategy-template.md');
|
|
78
|
+
const content = (0, fs_1.readFileSync)(templatePath, 'utf-8');
|
|
79
|
+
// Check platform strategies
|
|
80
|
+
(0, node_assert_1.default)(content.includes('### LinkedIn Strategy'), 'Should have LinkedIn strategy');
|
|
81
|
+
(0, node_assert_1.default)(content.includes('### Reddit Strategy'), 'Should have Reddit strategy');
|
|
82
|
+
(0, node_assert_1.default)(content.includes('### X (Twitter) Strategy'), 'Should have Twitter strategy');
|
|
83
|
+
(0, node_assert_1.default)(content.includes('### Facebook Strategy'), 'Should have Facebook strategy');
|
|
84
|
+
(0, node_assert_1.default)(content.includes('### Forum Strategy'), 'Should have Forum strategy');
|
|
85
|
+
(0, node_assert_1.default)(content.includes('### Web Search Strategy'), 'Should have Web Search strategy');
|
|
86
|
+
(0, node_assert_1.default)(content.includes('## Success Metrics per Platform'), 'Should have success metrics');
|
|
87
|
+
});
|
|
88
|
+
(0, node_test_1.it)('should have properly formatted CSV template', () => {
|
|
89
|
+
const templatePath = (0, path_1.join)(templatesPath, 'prospect-inventory-template.csv');
|
|
90
|
+
const content = (0, fs_1.readFileSync)(templatePath, 'utf-8');
|
|
91
|
+
// Check required CSV columns
|
|
92
|
+
const requiredColumns = [
|
|
93
|
+
'Name', 'Platform Found', 'Profile URL', 'Contact Information',
|
|
94
|
+
'Pain Points Identified', 'Relevance Score', 'Discovery Context',
|
|
95
|
+
'Follow-up Priority', 'Notes', 'Date Found', 'Industry',
|
|
96
|
+
'Job Title', 'Company', 'Location', 'Engagement Level'
|
|
97
|
+
];
|
|
98
|
+
const headerLine = content.split('\n')[0];
|
|
99
|
+
requiredColumns.forEach(column => {
|
|
100
|
+
(0, node_assert_1.default)(headerLine.includes(column), `CSV should include ${column} column`);
|
|
101
|
+
});
|
|
102
|
+
// Should have at least 2 sample rows
|
|
103
|
+
const lines = content.split('\n').filter(line => line.trim());
|
|
104
|
+
(0, node_assert_1.default)(lines.length >= 3, 'CSV should have header + at least 2 sample rows');
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
(0, node_test_1.describe)('AI Coach Phase Content', () => {
|
|
108
|
+
(0, node_test_1.it)('should have comprehensive Phase 1 coaching content', () => {
|
|
109
|
+
const phasePath = (0, path_1.join)(aiCoachPhasesPath, 'phase1-customer-profiling.md');
|
|
110
|
+
const content = (0, fs_1.readFileSync)(phasePath, 'utf-8');
|
|
111
|
+
(0, node_assert_1.default)(content.includes('## Objective'), 'Should have objective');
|
|
112
|
+
(0, node_assert_1.default)(content.includes('## Key Questions to Ask'), 'Should have coaching questions');
|
|
113
|
+
(0, node_assert_1.default)(content.includes('### Understanding the Business'), 'Should have business questions');
|
|
114
|
+
(0, node_assert_1.default)(content.includes('### Defining the Target Customer'), 'Should have customer questions');
|
|
115
|
+
(0, node_assert_1.default)(content.includes('### Identifying Pain Points'), 'Should have pain point questions');
|
|
116
|
+
(0, node_assert_1.default)(content.includes('## Validation Criteria'), 'Should have validation criteria');
|
|
117
|
+
(0, node_assert_1.default)(content.includes('## Evidence Required'), 'Should have evidence requirements');
|
|
118
|
+
// Should have at least 15 coaching questions
|
|
119
|
+
const questionMatches = content.match(/^\d+\.\s*"/gm);
|
|
120
|
+
(0, node_assert_1.default)(questionMatches && questionMatches.length >= 15, 'Should have at least 15 coaching questions');
|
|
121
|
+
});
|
|
122
|
+
(0, node_test_1.it)('should have browser automation guidance in Phase 2', () => {
|
|
123
|
+
const phasePath = (0, path_1.join)(aiCoachPhasesPath, 'phase2-platform-discovery.md');
|
|
124
|
+
const content = (0, fs_1.readFileSync)(phasePath, 'utf-8');
|
|
125
|
+
// Check browser automation integration
|
|
126
|
+
(0, node_assert_1.default)(content.includes('mcp_playwright_browser_navigate'), 'Should reference Playwright navigation');
|
|
127
|
+
(0, node_assert_1.default)(content.includes('mcp_playwright_browser_snapshot'), 'Should reference Playwright snapshots');
|
|
128
|
+
(0, node_assert_1.default)(content.includes('mcp_playwright_browser_click'), 'Should reference Playwright clicking');
|
|
129
|
+
(0, node_assert_1.default)(content.includes('Authentication Check'), 'Should have authentication handling');
|
|
130
|
+
// Check platform coverage
|
|
131
|
+
(0, node_assert_1.default)(content.includes('LinkedIn'), 'Should cover LinkedIn');
|
|
132
|
+
(0, node_assert_1.default)(content.includes('Reddit'), 'Should cover Reddit');
|
|
133
|
+
(0, node_assert_1.default)(content.includes('X (Twitter)'), 'Should cover Twitter');
|
|
134
|
+
(0, node_assert_1.default)(content.includes('Facebook'), 'Should cover Facebook');
|
|
135
|
+
(0, node_assert_1.default)(content.includes('Industry Forum Search'), 'Should cover forums');
|
|
136
|
+
(0, node_assert_1.default)(content.includes('General Web Search'), 'Should cover web search');
|
|
137
|
+
// Check authentication prompts
|
|
138
|
+
(0, node_assert_1.default)(content.includes('Please log into'), 'Should have login prompts');
|
|
139
|
+
(0, node_assert_1.default)(content.includes('Type \'ready\''), 'Should have confirmation prompts');
|
|
140
|
+
});
|
|
141
|
+
(0, node_test_1.it)('should have scoring system in Phase 3', () => {
|
|
142
|
+
const phasePath = (0, path_1.join)(aiCoachPhasesPath, 'phase3-prospect-qualification.md');
|
|
143
|
+
const content = (0, fs_1.readFileSync)(phasePath, 'utf-8');
|
|
144
|
+
(0, node_assert_1.default)(content.includes('## Scoring System (1-10 Scale)'), 'Should have scoring system');
|
|
145
|
+
(0, node_assert_1.default)(content.includes('Pain Point Match'), 'Should have pain point scoring');
|
|
146
|
+
(0, node_assert_1.default)(content.includes('Authority/Influence'), 'Should have authority scoring');
|
|
147
|
+
(0, node_assert_1.default)(content.includes('Urgency'), 'Should have urgency scoring');
|
|
148
|
+
(0, node_assert_1.default)(content.includes('Accessibility'), 'Should have accessibility scoring');
|
|
149
|
+
(0, node_assert_1.default)(content.includes('Engagement Level'), 'Should have engagement scoring');
|
|
150
|
+
// Check qualification tiers
|
|
151
|
+
(0, node_assert_1.default)(content.includes('Tier 1'), 'Should have tier 1 prospects');
|
|
152
|
+
(0, node_assert_1.default)(content.includes('Tier 2'), 'Should have tier 2 prospects');
|
|
153
|
+
(0, node_assert_1.default)(content.includes('Score 35-50'), 'Should define high-score prospects');
|
|
154
|
+
(0, node_assert_1.default)(content.includes('Score 25-34'), 'Should define medium-score prospects');
|
|
155
|
+
});
|
|
156
|
+
(0, node_test_1.it)('should have CSV compilation guidance in Phase 4', () => {
|
|
157
|
+
const phasePath = (0, path_1.join)(aiCoachPhasesPath, 'phase4-inventory-compilation.md');
|
|
158
|
+
const content = (0, fs_1.readFileSync)(phasePath, 'utf-8');
|
|
159
|
+
(0, node_assert_1.default)(content.includes('## CSV Structure'), 'Should have CSV structure');
|
|
160
|
+
(0, node_assert_1.default)(content.includes('### Required Columns'), 'Should define required columns');
|
|
161
|
+
(0, node_assert_1.default)(content.includes('### Step 2: Priority Assignment'), 'Should have priority assignment');
|
|
162
|
+
(0, node_assert_1.default)(content.includes('High Priority'), 'Should define high priority');
|
|
163
|
+
(0, node_assert_1.default)(content.includes('Medium Priority'), 'Should define medium priority');
|
|
164
|
+
(0, node_assert_1.default)(content.includes('Low Priority'), 'Should define low priority');
|
|
165
|
+
// Check file naming
|
|
166
|
+
(0, node_assert_1.default)(content.includes('users-to-target-{timestamp}.csv'), 'Should have file naming convention');
|
|
167
|
+
(0, node_assert_1.default)(content.includes('docs/customer-development/'), 'Should specify output location');
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
(0, node_test_1.describe)('Workflow Integration Points', () => {
|
|
171
|
+
(0, node_test_1.it)('should specify browser automation requirements', () => {
|
|
172
|
+
const mainContent = (0, fs_1.readFileSync)(mainWorkflowFile, 'utf-8');
|
|
173
|
+
(0, node_assert_1.default)(mainContent.includes('Playwright MCP'), 'Should mention Playwright MCP requirement');
|
|
174
|
+
(0, node_assert_1.default)(mainContent.includes('Browser automation'), 'Should mention browser automation');
|
|
175
|
+
});
|
|
176
|
+
(0, node_test_1.it)('should define success metrics', () => {
|
|
177
|
+
const mainContent = (0, fs_1.readFileSync)(mainWorkflowFile, 'utf-8');
|
|
178
|
+
(0, node_assert_1.default)(mainContent.includes('50-200 qualified prospects'), 'Should define prospect quantity target');
|
|
179
|
+
(0, node_assert_1.default)(mainContent.includes('70%+ relevance score'), 'Should define quality target');
|
|
180
|
+
(0, node_assert_1.default)(mainContent.includes('60%+ of prospects'), 'Should define contact info target');
|
|
181
|
+
});
|
|
182
|
+
(0, node_test_1.it)('should reference all template files', () => {
|
|
183
|
+
const mainContent = (0, fs_1.readFileSync)(mainWorkflowFile, 'utf-8');
|
|
184
|
+
(0, node_assert_1.default)(mainContent.includes('customer-persona-template.md'), 'Should reference persona template');
|
|
185
|
+
(0, node_assert_1.default)(mainContent.includes('search-strategy-template.md'), 'Should reference strategy template');
|
|
186
|
+
(0, node_assert_1.default)(mainContent.includes('prospect-inventory-template.csv'), 'Should reference CSV template');
|
|
187
|
+
});
|
|
188
|
+
(0, node_test_1.it)('should reference AI coach integration', () => {
|
|
189
|
+
const mainContent = (0, fs_1.readFileSync)(mainWorkflowFile, 'utf-8');
|
|
190
|
+
(0, node_assert_1.default)(mainContent.includes('seekCoachingOnNextStep'), 'Should reference AI coach integration');
|
|
191
|
+
(0, node_assert_1.default)(mainContent.includes('customer-development'), 'Should specify customer-development workflow type');
|
|
192
|
+
});
|
|
193
|
+
});
|
|
194
|
+
(0, node_test_1.describe)('Output Validation', () => {
|
|
195
|
+
(0, node_test_1.it)('should specify correct output file format', () => {
|
|
196
|
+
const phase4Content = (0, fs_1.readFileSync)((0, path_1.join)(aiCoachPhasesPath, 'phase4-inventory-compilation.md'), 'utf-8');
|
|
197
|
+
(0, node_assert_1.default)(phase4Content.includes('users-to-target-{YYYY-MM-DD-HHMM}.csv'), 'Should specify timestamp format');
|
|
198
|
+
(0, node_assert_1.default)(phase4Content.includes('docs/customer-development/'), 'Should specify output directory');
|
|
199
|
+
});
|
|
200
|
+
(0, node_test_1.it)('should define minimum success criteria', () => {
|
|
201
|
+
const phase4Content = (0, fs_1.readFileSync)((0, path_1.join)(aiCoachPhasesPath, 'phase4-inventory-compilation.md'), 'utf-8');
|
|
202
|
+
(0, node_assert_1.default)(phase4Content.includes('50+ qualified prospects'), 'Should define minimum prospects');
|
|
203
|
+
(0, node_assert_1.default)(phase4Content.includes('70%+ relevance score'), 'Should define minimum relevance');
|
|
204
|
+
(0, node_assert_1.default)(phase4Content.includes('60%+ of prospects'), 'Should define minimum contact success');
|
|
205
|
+
});
|
|
206
|
+
});
|
|
207
|
+
(0, node_test_1.describe)('Error Handling and Edge Cases', () => {
|
|
208
|
+
(0, node_test_1.it)('should include authentication failure handling', () => {
|
|
209
|
+
const phase2Content = (0, fs_1.readFileSync)((0, path_1.join)(aiCoachPhasesPath, 'phase2-platform-discovery.md'), 'utf-8');
|
|
210
|
+
(0, node_assert_1.default)(phase2Content.includes('Authentication Failures'), 'Should handle auth failures');
|
|
211
|
+
(0, node_assert_1.default)(phase2Content.includes('Rate Limiting'), 'Should handle rate limiting');
|
|
212
|
+
(0, node_assert_1.default)(phase2Content.includes('Technical Issues'), 'Should handle technical issues');
|
|
213
|
+
});
|
|
214
|
+
(0, node_test_1.it)('should include qualification edge cases', () => {
|
|
215
|
+
const phase3Content = (0, fs_1.readFileSync)((0, path_1.join)(aiCoachPhasesPath, 'phase3-prospect-qualification.md'), 'utf-8');
|
|
216
|
+
(0, node_assert_1.default)(phase3Content.includes('Common Pitfalls'), 'Should identify common pitfalls');
|
|
217
|
+
(0, node_assert_1.default)(phase3Content.includes('Over-Qualification'), 'Should warn about over-qualification');
|
|
218
|
+
(0, node_assert_1.default)(phase3Content.includes('Under-Qualification'), 'Should warn about under-qualification');
|
|
219
|
+
});
|
|
220
|
+
(0, node_test_1.it)('should include data quality validation', () => {
|
|
221
|
+
const phase4Content = (0, fs_1.readFileSync)((0, path_1.join)(aiCoachPhasesPath, 'phase4-inventory-compilation.md'), 'utf-8');
|
|
222
|
+
(0, node_assert_1.default)(phase4Content.includes('Data Validation'), 'Should include data validation');
|
|
223
|
+
(0, node_assert_1.default)(phase4Content.includes('Quality Assurance'), 'Should include QA checklist');
|
|
224
|
+
(0, node_assert_1.default)(phase4Content.includes('Remove Duplicates'), 'Should handle duplicates');
|
|
225
|
+
});
|
|
226
|
+
});
|
|
227
|
+
});
|
|
228
|
+
/**
|
|
229
|
+
* Integration test that would require actual browser automation
|
|
230
|
+
* This test is commented out as it requires:
|
|
231
|
+
* - Playwright MCP server running
|
|
232
|
+
* - Valid social media accounts
|
|
233
|
+
* - Network connectivity
|
|
234
|
+
* - Longer execution time
|
|
235
|
+
*/
|
|
236
|
+
/*
|
|
237
|
+
describe('Users to Target Integration Tests', () => {
|
|
238
|
+
it('should complete end-to-end workflow simulation', async () => {
|
|
239
|
+
// This would test:
|
|
240
|
+
// 1. Loading customer persona template
|
|
241
|
+
// 2. Simulating browser automation (with mocked responses)
|
|
242
|
+
// 3. Generating prospect data
|
|
243
|
+
// 4. Creating CSV output
|
|
244
|
+
// 5. Validating output format and content
|
|
245
|
+
|
|
246
|
+
// Implementation would require:
|
|
247
|
+
// - Mock Playwright MCP responses
|
|
248
|
+
// - Sample social media data
|
|
249
|
+
// - CSV validation logic
|
|
250
|
+
// - File system cleanup
|
|
251
|
+
});
|
|
252
|
+
});
|
|
253
|
+
*/
|
package/index.js
CHANGED
|
@@ -1,67 +1,56 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* FRAIM Framework -
|
|
5
|
-
*
|
|
6
|
-
* Where humans become AI managers through rigorous methodology
|
|
4
|
+
* FRAIM Framework - Smart Entry Point
|
|
5
|
+
* This file handles both production (dist/) and development (src/) environments.
|
|
7
6
|
*/
|
|
8
7
|
|
|
9
8
|
const path = require('path');
|
|
10
9
|
const fs = require('fs');
|
|
10
|
+
const { spawnSync } = require('child_process');
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
/**
|
|
13
|
+
* Runs the CLI using either the compiled JS or the source TS via tsx
|
|
14
|
+
*/
|
|
15
|
+
function runCLI() {
|
|
16
|
+
const distPath = path.join(__dirname, 'dist', 'src', 'cli', 'fraim.js');
|
|
17
|
+
const srcPath = path.join(__dirname, 'src', 'cli', 'fraim.ts');
|
|
14
18
|
|
|
15
|
-
//
|
|
16
|
-
|
|
19
|
+
// 1. Check if we have a compiled version (Production / CI)
|
|
20
|
+
if (fs.existsSync(distPath)) {
|
|
21
|
+
require(distPath);
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
17
24
|
|
|
18
|
-
//
|
|
19
|
-
if (
|
|
20
|
-
|
|
25
|
+
// 2. Fallback to source version using tsx (Development)
|
|
26
|
+
if (fs.existsSync(srcPath)) {
|
|
27
|
+
// We use spawnSync to run tsx so we don't have to require it in memory
|
|
28
|
+
// if it's not needed, and it handles the process arguments correctly.
|
|
29
|
+
const result = spawnSync('npx', ['tsx', srcPath, ...process.argv.slice(2)], {
|
|
30
|
+
stdio: 'inherit',
|
|
31
|
+
shell: true,
|
|
32
|
+
windowsHide: true
|
|
33
|
+
});
|
|
34
|
+
process.exit(result.status || 0);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
console.error('❌ FRAIM Error: Could not find CLI entry point.');
|
|
38
|
+
console.error('Expected one of:');
|
|
39
|
+
console.error(` - ${distPath}`);
|
|
40
|
+
console.error(` - ${srcPath}`);
|
|
41
|
+
process.exit(1);
|
|
21
42
|
}
|
|
22
43
|
|
|
23
|
-
//
|
|
24
|
-
module.exports
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
],
|
|
37
|
-
supportedAgents: ['cursor', 'claude', 'windsurf'],
|
|
38
|
-
repository: 'https://github.com/mathursrus/FRAIM',
|
|
39
|
-
note: 'All rules and workflows have been tested and proven in real project environments',
|
|
40
|
-
|
|
41
|
-
// New structure information
|
|
42
|
-
structure: {
|
|
43
|
-
rules: '/rules/',
|
|
44
|
-
workflows: '/workflows/',
|
|
45
|
-
templates: '/templates/',
|
|
46
|
-
scripts: '/scripts/',
|
|
47
|
-
github: '/.github/'
|
|
48
|
-
},
|
|
49
|
-
|
|
50
|
-
// Centralized rules
|
|
51
|
-
centralizedRules: [
|
|
52
|
-
'integrity-and-test-ethics.md',
|
|
53
|
-
'simplicity.md',
|
|
54
|
-
'architecture.md',
|
|
55
|
-
'continuous-learning.md',
|
|
56
|
-
'successful-debugging-patterns.md'
|
|
57
|
-
],
|
|
58
|
-
|
|
59
|
-
// Workflow templates
|
|
60
|
-
workflowTemplates: [
|
|
61
|
-
'design.md',
|
|
62
|
-
'implement.md',
|
|
63
|
-
'test.md',
|
|
64
|
-
'resolve.md',
|
|
65
|
-
'retrospect.md'
|
|
66
|
-
]
|
|
67
|
-
};
|
|
44
|
+
// Global programmatic exports
|
|
45
|
+
module.exports = {
|
|
46
|
+
FRAIM_INFO: {
|
|
47
|
+
name: 'FRAIM',
|
|
48
|
+
version: '2.0.54',
|
|
49
|
+
repository: 'https://github.com/mathursrus/FRAIM'
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
// If this file is run directly (via npx or global link), run the CLI
|
|
54
|
+
if (require.main === module) {
|
|
55
|
+
runCLI();
|
|
56
|
+
}
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fraim-framework",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.55",
|
|
4
4
|
"description": "FRAIM v2: Framework for Rigor-based AI Management - Transform from solo developer to AI manager orchestrating production-ready code with enterprise-grade discipline",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
7
|
-
"fraim": "./
|
|
8
|
-
"fraim-setup": "./
|
|
7
|
+
"fraim": "./index.js",
|
|
8
|
+
"fraim-setup": "./index.js"
|
|
9
9
|
},
|
|
10
10
|
"scripts": {
|
|
11
11
|
"setup": "node setup.js",
|
|
@@ -19,8 +19,8 @@
|
|
|
19
19
|
"watch:fraimlogs": "tsx scripts/watch-fraim-logs.ts",
|
|
20
20
|
"manage-keys": "tsx scripts/fraim/manage-keys.ts",
|
|
21
21
|
"view-signups": "tsx scripts/view-signups.ts",
|
|
22
|
-
"fraim:init": "npm run build && node
|
|
23
|
-
"fraim:sync": "node
|
|
22
|
+
"fraim:init": "npm run build && node index.js init",
|
|
23
|
+
"fraim:sync": "node index.js sync",
|
|
24
24
|
"postinstall": "fraim sync --skip-updates || echo 'FRAIM setup skipped.'",
|
|
25
25
|
"prepublishOnly": "npm run build",
|
|
26
26
|
"release": "npm version patch && npm publish",
|
|
@@ -1,63 +1,63 @@
|
|
|
1
|
-
# AI Agent Guardrails
|
|
2
|
-
|
|
3
|
-
This file references the centralized rules located in `rules/` to ensure consistency across all AI platforms.
|
|
4
|
-
|
|
5
|
-
## SUCCESS CRITERIA (THE "FRAIM 5")
|
|
6
|
-
**Source**: Retrieve via `get_fraim_file({ path: "rules/agent-success-criteria.md" })`
|
|
7
|
-
|
|
8
|
-
All agents are evaluated on:
|
|
9
|
-
1. **Integrity (100 pts)**: Honesty above all.
|
|
10
|
-
2. **Correctness (50 pts)**: Architecture & tests.
|
|
11
|
-
3. **Completeness (30 pts)**: Thoroughness.
|
|
12
|
-
4. **Independence (20 pts)**: Smart decisions.
|
|
13
|
-
5. **Speed (10 pts)**: Velocity.
|
|
14
|
-
|
|
15
|
-
## Referenced Rules
|
|
16
|
-
|
|
17
|
-
### 0. Integrity
|
|
18
|
-
**Source**: Retrieve via `get_fraim_file({ path: "rules/integrity-and-test-ethics.md" })`
|
|
19
|
-
|
|
20
|
-
THIS IS THE MOST CRITICAL RULE. Be ethical, truthful, honest above all.
|
|
21
|
-
|
|
22
|
-
### 1. Simplicity
|
|
23
|
-
**Source**: Retrieve via `get_fraim_file({ path: "rules/simplicity.md" })`
|
|
24
|
-
|
|
25
|
-
Keep solutions simple and focused, avoid over-engineering. Focus on the assigned issue only and don't make unrelated changes.
|
|
26
|
-
|
|
27
|
-
### 2. Communication
|
|
28
|
-
**Source**: Retrieve via `get_fraim_file({ path: "rules/communication.md" })`
|
|
29
|
-
|
|
30
|
-
Establish clear communication patterns and progress reporting standards for effective coordination between agents and stakeholders.
|
|
31
|
-
|
|
32
|
-
### 3. Architecture
|
|
33
|
-
**Source**: Read local architecture document (path from `.fraim/config.json` `customizations.architectureDoc`)
|
|
34
|
-
|
|
35
|
-
Maintain clean architectural boundaries by using BAML (LLM) for natural-language understanding and TypeScript for deterministic work.
|
|
36
|
-
|
|
37
|
-
### 4. Continuous Learning
|
|
38
|
-
**Source**: Retrieve via `get_fraim_file({ path: "rules/continuous-learning.md" })`
|
|
39
|
-
|
|
40
|
-
Prevent repeating past mistakes by systematically learning from retrospectives, RFCs, and historical issue patterns.
|
|
41
|
-
|
|
42
|
-
### 5. Agent Testing Guidelines
|
|
43
|
-
**Source**: Retrieve via `get_fraim_file({ path: "rules/agent-testing-guidelines.md" })`
|
|
44
|
-
|
|
45
|
-
Comprehensive testing and validation requirements with concrete evidence. Ensures all work is thoroughly validated before completion.
|
|
46
|
-
|
|
47
|
-
### 6. Local Development
|
|
48
|
-
**Source**: Retrieve via `get_fraim_file({ path: "rules/local-development.md" })`
|
|
49
|
-
|
|
50
|
-
Local development guidelines and workspace safety. Enables safe parallel development through strict workspace separation.
|
|
51
|
-
|
|
52
|
-
### 7. Software Development Lifecycle
|
|
53
|
-
**Source**: Retrieve via `get_fraim_file({ path: "rules/software-development-lifecycle.md" })`
|
|
54
|
-
|
|
55
|
-
### 9. Merge Requirements
|
|
56
|
-
**Source**: Retrieve via `get_fraim_file({ path: "rules/merge-requirements.md" })`
|
|
57
|
-
|
|
58
|
-
Enforces a strict `git rebase` workflow to ensure feature branches are up-to-date with `master` before merging, maintaining a clean and stable history.
|
|
59
|
-
|
|
60
|
-
### 10. Best practices while debuggin
|
|
61
|
-
**Source**: Retrieve via `get_fraim_file({ path: "rules/successful-debugging-patterns.md" })`
|
|
62
|
-
|
|
1
|
+
# AI Agent Guardrails
|
|
2
|
+
|
|
3
|
+
This file references the centralized rules located in `rules/` to ensure consistency across all AI platforms.
|
|
4
|
+
|
|
5
|
+
## SUCCESS CRITERIA (THE "FRAIM 5")
|
|
6
|
+
**Source**: Retrieve via `get_fraim_file({ path: "rules/agent-success-criteria.md" })`
|
|
7
|
+
|
|
8
|
+
All agents are evaluated on:
|
|
9
|
+
1. **Integrity (100 pts)**: Honesty above all.
|
|
10
|
+
2. **Correctness (50 pts)**: Architecture & tests.
|
|
11
|
+
3. **Completeness (30 pts)**: Thoroughness.
|
|
12
|
+
4. **Independence (20 pts)**: Smart decisions.
|
|
13
|
+
5. **Speed (10 pts)**: Velocity.
|
|
14
|
+
|
|
15
|
+
## Referenced Rules
|
|
16
|
+
|
|
17
|
+
### 0. Integrity
|
|
18
|
+
**Source**: Retrieve via `get_fraim_file({ path: "rules/integrity-and-test-ethics.md" })`
|
|
19
|
+
|
|
20
|
+
THIS IS THE MOST CRITICAL RULE. Be ethical, truthful, honest above all.
|
|
21
|
+
|
|
22
|
+
### 1. Simplicity
|
|
23
|
+
**Source**: Retrieve via `get_fraim_file({ path: "rules/simplicity.md" })`
|
|
24
|
+
|
|
25
|
+
Keep solutions simple and focused, avoid over-engineering. Focus on the assigned issue only and don't make unrelated changes.
|
|
26
|
+
|
|
27
|
+
### 2. Communication
|
|
28
|
+
**Source**: Retrieve via `get_fraim_file({ path: "rules/communication.md" })`
|
|
29
|
+
|
|
30
|
+
Establish clear communication patterns and progress reporting standards for effective coordination between agents and stakeholders.
|
|
31
|
+
|
|
32
|
+
### 3. Architecture
|
|
33
|
+
**Source**: Read local architecture document (path from `.fraim/config.json` `customizations.architectureDoc`)
|
|
34
|
+
|
|
35
|
+
Maintain clean architectural boundaries by using BAML (LLM) for natural-language understanding and TypeScript for deterministic work.
|
|
36
|
+
|
|
37
|
+
### 4. Continuous Learning
|
|
38
|
+
**Source**: Retrieve via `get_fraim_file({ path: "rules/continuous-learning.md" })`
|
|
39
|
+
|
|
40
|
+
Prevent repeating past mistakes by systematically learning from retrospectives, RFCs, and historical issue patterns.
|
|
41
|
+
|
|
42
|
+
### 5. Agent Testing Guidelines
|
|
43
|
+
**Source**: Retrieve via `get_fraim_file({ path: "rules/agent-testing-guidelines.md" })`
|
|
44
|
+
|
|
45
|
+
Comprehensive testing and validation requirements with concrete evidence. Ensures all work is thoroughly validated before completion.
|
|
46
|
+
|
|
47
|
+
### 6. Local Development
|
|
48
|
+
**Source**: Retrieve via `get_fraim_file({ path: "rules/local-development.md" })`
|
|
49
|
+
|
|
50
|
+
Local development guidelines and workspace safety. Enables safe parallel development through strict workspace separation.
|
|
51
|
+
|
|
52
|
+
### 7. Software Development Lifecycle
|
|
53
|
+
**Source**: Retrieve via `get_fraim_file({ path: "rules/software-development-lifecycle.md" })`
|
|
54
|
+
|
|
55
|
+
### 9. Merge Requirements
|
|
56
|
+
**Source**: Retrieve via `get_fraim_file({ path: "rules/merge-requirements.md" })`
|
|
57
|
+
|
|
58
|
+
Enforces a strict `git rebase` workflow to ensure feature branches are up-to-date with `master` before merging, maintaining a clean and stable history.
|
|
59
|
+
|
|
60
|
+
### 10. Best practices while debuggin
|
|
61
|
+
**Source**: Retrieve via `get_fraim_file({ path: "rules/successful-debugging-patterns.md" })`
|
|
62
|
+
|
|
63
63
|
Patterns on debugging issues systematically and converting learnings into test cases
|
|
@@ -1,38 +1,38 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
|
|
3
|
-
# Detect Tautological Tests
|
|
4
|
-
# This script scans test files for patterns that suggest tests are validating code structure
|
|
5
|
-
# (interfaces, enums) rather than runtime behavior.
|
|
6
|
-
|
|
7
|
-
echo "🔍 Scanning for Tautological Test Patterns..."
|
|
8
|
-
ERROR_FOUND=0
|
|
9
|
-
|
|
10
|
-
# Pattern 1: Asserting an array literal equals another array literal (common in enum testing)
|
|
11
|
-
# Looks for: assert.deepEqual(['a', 'b'], ['a', 'b'])
|
|
12
|
-
if grep -rE "assert\.(deep)?(Strict)?Equal\(\[.*\], \[.*\]\)" test*.ts; then
|
|
13
|
-
echo "❌ ERROR: Found potential tautological array comparison. Tests should verify app logic, not hardcoded arrays."
|
|
14
|
-
echo " Rationale: Testing that ['A'] equals ['A'] validates nothing about the application."
|
|
15
|
-
ERROR_FOUND=1
|
|
16
|
-
fi
|
|
17
|
-
|
|
18
|
-
# Pattern 2: Asserting properties on an object literal defined in the test (Type/Interface testing)
|
|
19
|
-
# Simplified: Look for defining a typed object and immediately asserting on it in the same file
|
|
20
|
-
# This is hard to do robustly with just grep, so we'll rely on the Naming Convention check for now.
|
|
21
|
-
|
|
22
|
-
# Pattern 3: Test names that explicitly say "Validate Enums", "Validate Fields", etc.
|
|
23
|
-
# We match "Validate TaskStatus Enums" or similar phrases
|
|
24
|
-
if grep -riE "['\"]Unit: Validate (Enum|Constant|Interface|Type|Field|Object|TaskStatus|Task Object)" test*.ts; then
|
|
25
|
-
echo "❌ ERROR: Found test descriptions explicitly claiming to validate Enums/Types/Fields."
|
|
26
|
-
echo " Rationale: Unit tests should validate BEHAVIOR (e.g., 'persists correct status'), not definitions."
|
|
27
|
-
ERROR_FOUND=1
|
|
28
|
-
fi
|
|
29
|
-
|
|
30
|
-
if [ $ERROR_FOUND -eq 1 ]; then
|
|
31
|
-
echo ""
|
|
32
|
-
echo "⚠️ Potential Anti-Patterns Detected."
|
|
33
|
-
echo " Please review the identified tests against rules/integrity-and-test-ethics.md"
|
|
34
|
-
exit 1
|
|
35
|
-
else
|
|
36
|
-
echo "✅ No obvious tautological patterns found."
|
|
37
|
-
exit 0
|
|
38
|
-
fi
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# Detect Tautological Tests
|
|
4
|
+
# This script scans test files for patterns that suggest tests are validating code structure
|
|
5
|
+
# (interfaces, enums) rather than runtime behavior.
|
|
6
|
+
|
|
7
|
+
echo "🔍 Scanning for Tautological Test Patterns..."
|
|
8
|
+
ERROR_FOUND=0
|
|
9
|
+
|
|
10
|
+
# Pattern 1: Asserting an array literal equals another array literal (common in enum testing)
|
|
11
|
+
# Looks for: assert.deepEqual(['a', 'b'], ['a', 'b'])
|
|
12
|
+
if grep -rE "assert\.(deep)?(Strict)?Equal\(\[.*\], \[.*\]\)" test*.ts; then
|
|
13
|
+
echo "❌ ERROR: Found potential tautological array comparison. Tests should verify app logic, not hardcoded arrays."
|
|
14
|
+
echo " Rationale: Testing that ['A'] equals ['A'] validates nothing about the application."
|
|
15
|
+
ERROR_FOUND=1
|
|
16
|
+
fi
|
|
17
|
+
|
|
18
|
+
# Pattern 2: Asserting properties on an object literal defined in the test (Type/Interface testing)
|
|
19
|
+
# Simplified: Look for defining a typed object and immediately asserting on it in the same file
|
|
20
|
+
# This is hard to do robustly with just grep, so we'll rely on the Naming Convention check for now.
|
|
21
|
+
|
|
22
|
+
# Pattern 3: Test names that explicitly say "Validate Enums", "Validate Fields", etc.
|
|
23
|
+
# We match "Validate TaskStatus Enums" or similar phrases
|
|
24
|
+
if grep -riE "['\"]Unit: Validate (Enum|Constant|Interface|Type|Field|Object|TaskStatus|Task Object)" test*.ts; then
|
|
25
|
+
echo "❌ ERROR: Found test descriptions explicitly claiming to validate Enums/Types/Fields."
|
|
26
|
+
echo " Rationale: Unit tests should validate BEHAVIOR (e.g., 'persists correct status'), not definitions."
|
|
27
|
+
ERROR_FOUND=1
|
|
28
|
+
fi
|
|
29
|
+
|
|
30
|
+
if [ $ERROR_FOUND -eq 1 ]; then
|
|
31
|
+
echo ""
|
|
32
|
+
echo "⚠️ Potential Anti-Patterns Detected."
|
|
33
|
+
echo " Please review the identified tests against rules/integrity-and-test-ethics.md"
|
|
34
|
+
exit 1
|
|
35
|
+
else
|
|
36
|
+
echo "✅ No obvious tautological patterns found."
|
|
37
|
+
exit 0
|
|
38
|
+
fi
|