fraim-framework 2.0.26 → 2.0.27
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/src/cli/commands/init.js +2 -0
- package/dist/src/cli/commands/sync.js +17 -0
- package/dist/src/fraim/config-loader.js +0 -8
- package/dist/src/fraim/setup-wizard.js +1 -69
- package/dist/src/fraim/types.js +0 -11
- package/dist/src/utils/version-utils.js +32 -0
- package/dist/tests/test-cli.js +0 -2
- package/dist/tests/test-genericization.js +0 -2
- package/dist/tests/test-sync-version-update.js +93 -0
- package/package.json +1 -1
|
@@ -12,6 +12,7 @@ const first_run_js_1 = require("../setup/first-run.js");
|
|
|
12
12
|
const sync_js_1 = require("./sync.js");
|
|
13
13
|
const types_js_1 = require("../../fraim/types.js");
|
|
14
14
|
const git_utils_js_1 = require("../../utils/git-utils.js");
|
|
15
|
+
const version_utils_js_1 = require("../../utils/version-utils.js");
|
|
15
16
|
const runInit = async () => {
|
|
16
17
|
const projectRoot = process.cwd();
|
|
17
18
|
const fraimDir = path_1.default.join(projectRoot, '.fraim');
|
|
@@ -28,6 +29,7 @@ const runInit = async () => {
|
|
|
28
29
|
const remoteInfo = (0, git_utils_js_1.getGitRemoteInfo)();
|
|
29
30
|
const config = {
|
|
30
31
|
...types_js_1.DEFAULT_FRAIM_CONFIG,
|
|
32
|
+
version: (0, version_utils_js_1.getFraimVersion)(),
|
|
31
33
|
project: {
|
|
32
34
|
...types_js_1.DEFAULT_FRAIM_CONFIG.project,
|
|
33
35
|
name: path_1.default.basename(projectRoot)
|
|
@@ -11,6 +11,7 @@ const chalk_1 = __importDefault(require("chalk"));
|
|
|
11
11
|
const digest_utils_1 = require("../../utils/digest-utils");
|
|
12
12
|
const stub_generator_1 = require("../../utils/stub-generator");
|
|
13
13
|
const config_loader_js_1 = require("../../fraim/config-loader.js");
|
|
14
|
+
const version_utils_js_1 = require("../../utils/version-utils.js");
|
|
14
15
|
const runSync = async (options) => {
|
|
15
16
|
const projectRoot = process.cwd();
|
|
16
17
|
const config = (0, config_loader_js_1.loadFraimConfig)();
|
|
@@ -37,6 +38,22 @@ const runSync = async (options) => {
|
|
|
37
38
|
if (!fs_1.default.existsSync(workflowsDir)) {
|
|
38
39
|
fs_1.default.mkdirSync(workflowsDir, { recursive: true });
|
|
39
40
|
}
|
|
41
|
+
// Update version in config.json
|
|
42
|
+
const configPath = path_1.default.join(fraimDir, 'config.json');
|
|
43
|
+
if (fs_1.default.existsSync(configPath)) {
|
|
44
|
+
try {
|
|
45
|
+
const currentConfig = JSON.parse(fs_1.default.readFileSync(configPath, 'utf8'));
|
|
46
|
+
const newVersion = (0, version_utils_js_1.getFraimVersion)();
|
|
47
|
+
if (currentConfig.version !== newVersion) {
|
|
48
|
+
currentConfig.version = newVersion;
|
|
49
|
+
fs_1.default.writeFileSync(configPath, JSON.stringify(currentConfig, null, 2));
|
|
50
|
+
console.log(chalk_1.default.green(`✅ Updated FRAIM version to ${newVersion} in config.`));
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
catch (e) {
|
|
54
|
+
console.warn(chalk_1.default.yellow('⚠️ Could not update version in config.json.'));
|
|
55
|
+
}
|
|
56
|
+
}
|
|
40
57
|
console.log(chalk_1.default.blue('🔄 Syncing FRAIM workflows...'));
|
|
41
58
|
const currentDigest = await (0, digest_utils_1.generateDigest)(registryPath);
|
|
42
59
|
const existingDigest = fs_1.default.existsSync(digestPath) ? fs_1.default.readFileSync(digestPath, 'utf8') : '';
|
|
@@ -38,14 +38,6 @@ function loadFraimConfig() {
|
|
|
38
38
|
...types_1.DEFAULT_FRAIM_CONFIG.customizations,
|
|
39
39
|
...(config.customizations || {})
|
|
40
40
|
},
|
|
41
|
-
architecture: {
|
|
42
|
-
...types_1.DEFAULT_FRAIM_CONFIG.architecture,
|
|
43
|
-
...(config.architecture || {})
|
|
44
|
-
},
|
|
45
|
-
testing: {
|
|
46
|
-
...types_1.DEFAULT_FRAIM_CONFIG.testing,
|
|
47
|
-
...(config.testing || {})
|
|
48
|
-
},
|
|
49
41
|
persona: {
|
|
50
42
|
...types_1.DEFAULT_FRAIM_CONFIG.persona,
|
|
51
43
|
...(config.persona || {})
|
|
@@ -7,8 +7,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
7
7
|
exports.generateConfigFromAnswers = generateConfigFromAnswers;
|
|
8
8
|
exports.writeConfig = writeConfig;
|
|
9
9
|
exports.createDirectoryStructure = createDirectoryStructure;
|
|
10
|
-
exports.generateArchitectureTemplate = generateArchitectureTemplate;
|
|
11
|
-
exports.writeArchitectureTemplate = writeArchitectureTemplate;
|
|
12
10
|
exports.runSetup = runSetup;
|
|
13
11
|
const fs_1 = require("fs");
|
|
14
12
|
const path_1 = require("path");
|
|
@@ -65,70 +63,6 @@ function createDirectoryStructure() {
|
|
|
65
63
|
}
|
|
66
64
|
}
|
|
67
65
|
}
|
|
68
|
-
/**
|
|
69
|
-
* Generate architecture.md template
|
|
70
|
-
*/
|
|
71
|
-
function generateArchitectureTemplate(config) {
|
|
72
|
-
const arch = config.architecture;
|
|
73
|
-
let template = `# Project Architecture
|
|
74
|
-
|
|
75
|
-
This document describes the architecture patterns and conventions for ${config.project.name}.
|
|
76
|
-
|
|
77
|
-
## Overview
|
|
78
|
-
|
|
79
|
-
- **Project Name:** ${config.project.name}
|
|
80
|
-
- **Project Type:** ${config.project.type || 'Not specified'}
|
|
81
|
-
- **Primary Language:** ${config.project.primaryLanguage || 'Not specified'}
|
|
82
|
-
- **Database:** ${config.project.database || 'Not specified'}
|
|
83
|
-
- **ORM:** ${config.project.orm || 'Not specified'}
|
|
84
|
-
|
|
85
|
-
`;
|
|
86
|
-
if (arch) {
|
|
87
|
-
template += `## Architecture Pattern
|
|
88
|
-
|
|
89
|
-
**Pattern:** ${arch.pattern || 'Not specified'}
|
|
90
|
-
|
|
91
|
-
`;
|
|
92
|
-
if (arch.llmFramework) {
|
|
93
|
-
template += `### LLM Integration
|
|
94
|
-
|
|
95
|
-
- **Framework:** ${arch.llmFramework}
|
|
96
|
-
- **Usage:** ${arch.llmUsage?.join(', ') || 'Not specified'}
|
|
97
|
-
- **Deterministic Usage:** ${arch.deterministicUsage?.join(', ') || 'Not specified'}
|
|
98
|
-
|
|
99
|
-
`;
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
template += `## Development Guidelines
|
|
103
|
-
|
|
104
|
-
### Testing
|
|
105
|
-
- **Framework:** ${config.testing?.framework || 'Not specified'}
|
|
106
|
-
- **Test Location:** ${config.testing?.testLocation || 'Not specified'}
|
|
107
|
-
- **Test Naming:** ${config.testing?.testNaming || 'Not specified'}
|
|
108
|
-
|
|
109
|
-
### Git Workflow
|
|
110
|
-
- **Default Branch:** ${config.git.defaultBranch}
|
|
111
|
-
|
|
112
|
-
## Customization
|
|
113
|
-
|
|
114
|
-
This project uses FRAIM with customizations in \`.fraim/\`:
|
|
115
|
-
- Custom rules: \`.fraim/rules/\`
|
|
116
|
-
- Custom workflows: \`.fraim/workflows/\`
|
|
117
|
-
- Custom templates: \`.fraim/templates/\`
|
|
118
|
-
- Custom scripts: \`.fraim/scripts/\`
|
|
119
|
-
`;
|
|
120
|
-
return template;
|
|
121
|
-
}
|
|
122
|
-
/**
|
|
123
|
-
* Write architecture.md template
|
|
124
|
-
*/
|
|
125
|
-
function writeArchitectureTemplate(config) {
|
|
126
|
-
const fraimDir = (0, path_1.join)(process.cwd(), '.fraim');
|
|
127
|
-
const archPath = (0, path_1.join)(fraimDir, 'architecture.md');
|
|
128
|
-
const template = generateArchitectureTemplate(config);
|
|
129
|
-
(0, fs_1.writeFileSync)(archPath, template, 'utf-8');
|
|
130
|
-
console.log(`✅ Created .fraim/architecture.md`);
|
|
131
|
-
}
|
|
132
66
|
/**
|
|
133
67
|
* Run setup wizard
|
|
134
68
|
*/
|
|
@@ -148,11 +82,9 @@ function runSetup(answers) {
|
|
|
148
82
|
createDirectoryStructure();
|
|
149
83
|
// Write config
|
|
150
84
|
writeConfig(config);
|
|
151
|
-
// Write architecture template
|
|
152
|
-
writeArchitectureTemplate(config);
|
|
153
85
|
return {
|
|
154
86
|
success: true,
|
|
155
|
-
message: `✅ FRAIM setup complete!\n\nCreated:\n- .fraim/config.json\n-
|
|
87
|
+
message: `✅ FRAIM setup complete!\n\nCreated:\n- .fraim/config.json\n- Directory structure\n\nNext steps:\n1. Review .fraim/config.json and adjust as needed\n2. Add custom rules to .fraim/rules/\n3. Add custom workflows to .fraim/workflows/\n4. Customize templates in .fraim/templates/`,
|
|
156
88
|
config
|
|
157
89
|
};
|
|
158
90
|
}
|
package/dist/src/fraim/types.js
CHANGED
|
@@ -18,17 +18,6 @@ exports.DEFAULT_FRAIM_CONFIG = {
|
|
|
18
18
|
repoOwner: '',
|
|
19
19
|
repoName: ''
|
|
20
20
|
},
|
|
21
|
-
architecture: {
|
|
22
|
-
pattern: 'llm-deterministic-separation',
|
|
23
|
-
llmFramework: 'baml',
|
|
24
|
-
llmUsage: [],
|
|
25
|
-
deterministicUsage: ['data-processing', 'api-calls']
|
|
26
|
-
},
|
|
27
|
-
testing: {
|
|
28
|
-
framework: 'tsx-test',
|
|
29
|
-
testLocation: 'root',
|
|
30
|
-
testNaming: 'test-*.ts'
|
|
31
|
-
},
|
|
32
21
|
customizations: {
|
|
33
22
|
workflowsPath: '.fraim/workflows'
|
|
34
23
|
},
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.getFraimVersion = getFraimVersion;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
function getFraimVersion() {
|
|
10
|
+
// Try reliable paths to find package.json relative to this file
|
|
11
|
+
// locally: src/utils/version-utils.ts -> package.json is ../../package.json
|
|
12
|
+
// dist: dist/src/utils/version-utils.js -> package.json is ../../../package.json
|
|
13
|
+
const possiblePaths = [
|
|
14
|
+
path_1.default.join(__dirname, '../../package.json'), // Local dev (src)
|
|
15
|
+
path_1.default.join(__dirname, '../../../package.json'), // Dist (dist/src)
|
|
16
|
+
path_1.default.join(process.cwd(), 'package.json') // Fallback to CWD (unlikely to be correct for global install but safe fallback)
|
|
17
|
+
];
|
|
18
|
+
for (const pkgPath of possiblePaths) {
|
|
19
|
+
if (fs_1.default.existsSync(pkgPath)) {
|
|
20
|
+
try {
|
|
21
|
+
const pkg = JSON.parse(fs_1.default.readFileSync(pkgPath, 'utf-8'));
|
|
22
|
+
if (pkg.name === 'fraim-framework') {
|
|
23
|
+
return pkg.version;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
catch (e) {
|
|
27
|
+
// Ignore parsing errors
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return '1.0.0'; // Fallback
|
|
32
|
+
}
|
package/dist/tests/test-cli.js
CHANGED
|
@@ -110,8 +110,6 @@ async function testCliLifecycle() {
|
|
|
110
110
|
}
|
|
111
111
|
node_assert_1.default.ok(config.customizations, 'config.customizations should exist');
|
|
112
112
|
node_assert_1.default.strictEqual(config.customizations.workflowsPath, '.fraim/workflows');
|
|
113
|
-
node_assert_1.default.ok(config.architecture, 'architecture should be in generated config');
|
|
114
|
-
node_assert_1.default.ok(config.testing, 'testing should be in generated config');
|
|
115
113
|
node_assert_1.default.ok(!config.mcp, 'mcp should not be in generated config');
|
|
116
114
|
// 2. Test `fraim sync`
|
|
117
115
|
// We need a fake registry for sync to work against
|
|
@@ -12,8 +12,6 @@ async function testConfigDefaults() {
|
|
|
12
12
|
try {
|
|
13
13
|
node_assert_1.default.strictEqual(types_1.DEFAULT_FRAIM_CONFIG.persona.name, 'AI Agent', 'Default persona name should be "AI Agent"');
|
|
14
14
|
node_assert_1.default.ok(types_1.DEFAULT_FRAIM_CONFIG.customizations?.workflowsPath, 'workflowsPath should exist');
|
|
15
|
-
node_assert_1.default.ok(types_1.DEFAULT_FRAIM_CONFIG.architecture, 'architecture should be restored');
|
|
16
|
-
node_assert_1.default.ok(types_1.DEFAULT_FRAIM_CONFIG.testing, 'testing should be restored');
|
|
17
15
|
node_assert_1.default.ok(!types_1.DEFAULT_FRAIM_CONFIG.mcp, 'mcp should still be removed');
|
|
18
16
|
return true;
|
|
19
17
|
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const node_child_process_1 = require("node:child_process");
|
|
7
|
+
const test_utils_1 = require("./test-utils");
|
|
8
|
+
const node_assert_1 = __importDefault(require("node:assert"));
|
|
9
|
+
const fs_1 = __importDefault(require("fs"));
|
|
10
|
+
const path_1 = __importDefault(require("path"));
|
|
11
|
+
const os_1 = __importDefault(require("os"));
|
|
12
|
+
const version_utils_1 = require("../src/utils/version-utils");
|
|
13
|
+
const types_1 = require("../src/fraim/types");
|
|
14
|
+
async function testSyncUpdateVersion() {
|
|
15
|
+
console.log(' 🚀 Testing "fraim sync" version update...');
|
|
16
|
+
// Create a temp directory for the test project
|
|
17
|
+
const tempDir = fs_1.default.mkdtempSync(path_1.default.join(os_1.default.tmpdir(), 'fraim-test-sync-'));
|
|
18
|
+
console.log(` 📂 Created temp dir: ${tempDir}`);
|
|
19
|
+
try {
|
|
20
|
+
const platform = process.platform;
|
|
21
|
+
const npx = platform === 'win32' ? 'npx.cmd' : 'npx';
|
|
22
|
+
const cliScript = path_1.default.resolve(__dirname, '../src/cli/fraim.ts');
|
|
23
|
+
// Setup .fraim/config.json with an OLD version
|
|
24
|
+
const fraimDir = path_1.default.join(tempDir, '.fraim');
|
|
25
|
+
fs_1.default.mkdirSync(fraimDir, { recursive: true });
|
|
26
|
+
const oldVersion = '0.0.0';
|
|
27
|
+
const initialConfig = {
|
|
28
|
+
...types_1.DEFAULT_FRAIM_CONFIG,
|
|
29
|
+
version: oldVersion,
|
|
30
|
+
project: { name: 'test-project' },
|
|
31
|
+
git: { repoOwner: 'test', repoName: 'test' }
|
|
32
|
+
};
|
|
33
|
+
fs_1.default.writeFileSync(path_1.default.join(fraimDir, 'config.json'), JSON.stringify(initialConfig, null, 2));
|
|
34
|
+
// Create a fake registry so sync doesn't fail hard
|
|
35
|
+
const registryDir = path_1.default.join(tempDir, 'registry', 'workflows');
|
|
36
|
+
fs_1.default.mkdirSync(registryDir, { recursive: true });
|
|
37
|
+
fs_1.default.writeFileSync(path_1.default.join(registryDir, 'dummy.md'), '---\nintent: test\n---\n# Dummy');
|
|
38
|
+
// Helper to run CLI commands
|
|
39
|
+
const runFraim = (args) => {
|
|
40
|
+
return new Promise((resolve) => {
|
|
41
|
+
const ps = (0, node_child_process_1.spawn)(npx, ['tsx', `"${cliScript}"`, ...args], {
|
|
42
|
+
cwd: tempDir,
|
|
43
|
+
env: { ...process.env, TEST_MODE: 'true' },
|
|
44
|
+
shell: true
|
|
45
|
+
});
|
|
46
|
+
let stdout = '';
|
|
47
|
+
let stderr = '';
|
|
48
|
+
ps.stdout.on('data', d => stdout += d.toString());
|
|
49
|
+
ps.stderr.on('data', d => stderr += d.toString());
|
|
50
|
+
ps.on('close', (code) => resolve({ stdout, stderr, code }));
|
|
51
|
+
});
|
|
52
|
+
};
|
|
53
|
+
// Run `fraim sync`
|
|
54
|
+
console.log(' Running "fraim sync"...');
|
|
55
|
+
const res = await runFraim(['sync']);
|
|
56
|
+
if (res.code !== 0) {
|
|
57
|
+
console.error(' ❌ Sync failed:', res.stderr);
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
// Verify config.json has the NEW/Current version
|
|
61
|
+
const updatedConfig = JSON.parse(fs_1.default.readFileSync(path_1.default.join(fraimDir, 'config.json'), 'utf-8'));
|
|
62
|
+
const currentPackageVersion = (0, version_utils_1.getFraimVersion)();
|
|
63
|
+
console.log(` ℹ️ Old Version: ${oldVersion}`);
|
|
64
|
+
console.log(` ℹ️ New Version in Config: ${updatedConfig.version}`);
|
|
65
|
+
console.log(` ℹ️ Current Package Version: ${currentPackageVersion}`);
|
|
66
|
+
node_assert_1.default.strictEqual(updatedConfig.version, currentPackageVersion, 'Config version should match package version after sync');
|
|
67
|
+
node_assert_1.default.notStrictEqual(updatedConfig.version, oldVersion, 'Config version should have been updated from 0.0.0');
|
|
68
|
+
console.log(' ✅ Validated: Version was updated correctly.');
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
console.error(' ❌ Test failed:', error);
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
finally {
|
|
76
|
+
try {
|
|
77
|
+
fs_1.default.rmSync(tempDir, { recursive: true, force: true });
|
|
78
|
+
}
|
|
79
|
+
catch (e) { }
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
async function runTest(testCase) {
|
|
83
|
+
return await testCase.testFunction();
|
|
84
|
+
}
|
|
85
|
+
const testCases = [
|
|
86
|
+
{
|
|
87
|
+
name: 'Sync Version Update',
|
|
88
|
+
description: 'Verifies that fraim sync updates the version in config.json',
|
|
89
|
+
testFunction: testSyncUpdateVersion,
|
|
90
|
+
tags: ['cli', 'sync']
|
|
91
|
+
},
|
|
92
|
+
];
|
|
93
|
+
(0, test_utils_1.runTests)(testCases, runTest, 'Fraim Sync Update Tests');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fraim-framework",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.27",
|
|
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": {
|