fraim 2.0.358-next.1 → 2.0.358-next.2
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
CHANGED
|
@@ -343,7 +343,7 @@ fraim/
|
|
|
343
343
|
Use `fraim override` to create a local starting point:
|
|
344
344
|
|
|
345
345
|
```bash
|
|
346
|
-
fraim override --inherit jobs/
|
|
346
|
+
fraim override --inherit jobs/engineering/feature-implementation.md
|
|
347
347
|
fraim override --copy rules/engineering/architecture-standards.md
|
|
348
348
|
```
|
|
349
349
|
|
|
@@ -15,6 +15,7 @@ const fs_1 = __importDefault(require("fs"));
|
|
|
15
15
|
const os_1 = __importDefault(require("os"));
|
|
16
16
|
const path_1 = __importDefault(require("path"));
|
|
17
17
|
const windows_shim_path_search_1 = require("../../core/utils/windows-shim-path-search");
|
|
18
|
+
const user_config_1 = require("../utils/user-config");
|
|
18
19
|
const LAUNCHER_VERSION = 2;
|
|
19
20
|
/**
|
|
20
21
|
* Issue #1354: how long a resolved version stays good before the launcher asks npm again.
|
|
@@ -82,7 +83,8 @@ const CHANNEL = (() => {
|
|
|
82
83
|
return '';
|
|
83
84
|
})();
|
|
84
85
|
const DIST_TAG = CHANNEL.toUpperCase() === 'PPE' ? 'next' : 'latest';
|
|
85
|
-
|
|
86
|
+
// Preserve the stable cache written by earlier launchers and explicit sync.
|
|
87
|
+
const STATE_PATH = path.join(STATE_DIR, DIST_TAG === 'latest' ? 'latest.json' : 'latest-next.json');
|
|
86
88
|
const CACHE_ROOT = path.join(USER_DIR, 'npm-cache', 'mcp');
|
|
87
89
|
const REFRESH_LOCK = path.join(STATE_DIR, 'refresh-' + DIST_TAG + '.lock');
|
|
88
90
|
const REFRESH_LOCK_STALE_MS = 10 * 60 * 1000;
|
|
@@ -114,11 +116,17 @@ function ensureDir(dir) {
|
|
|
114
116
|
}
|
|
115
117
|
|
|
116
118
|
function readState() {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
119
|
+
// Stable releases have shipped both filenames. Preserve the latest selection
|
|
120
|
+
// across upgrades, including an explicit sync that deliberately selects an older version.
|
|
121
|
+
const paths = DIST_TAG === 'latest'
|
|
122
|
+
? [STATE_PATH, path.join(STATE_DIR, 'latest-latest.json')]
|
|
123
|
+
: [STATE_PATH, path.join(STATE_DIR, 'latest.json')];
|
|
124
|
+
const states = paths.flatMap(file => {
|
|
125
|
+
try { const state = JSON.parse(fs.readFileSync(file, 'utf8')); return isUsableState(state) ? [state] : []; }
|
|
126
|
+
catch { return []; }
|
|
127
|
+
});
|
|
128
|
+
states.sort((a, b) => (Date.parse(b.updatedAt) || 0) - (Date.parse(a.updatedAt) || 0));
|
|
129
|
+
return states[0] || null;
|
|
122
130
|
}
|
|
123
131
|
|
|
124
132
|
function writeState(state) {
|
|
@@ -161,7 +169,8 @@ function isUsableState(state) {
|
|
|
161
169
|
state &&
|
|
162
170
|
state.packageName === 'fraim' &&
|
|
163
171
|
state.binName === 'fraim' &&
|
|
164
|
-
|
|
172
|
+
// Older explicit sync wrote PPE versions into latest.json without a tag.
|
|
173
|
+
(state.distTag || (typeof state.version === 'string' && /-next(?:[.]|$)/.test(state.version) ? 'next' : 'latest')) === DIST_TAG &&
|
|
165
174
|
typeof state.version === 'string' &&
|
|
166
175
|
/^\\d+\\.\\d+\\.\\d+/.test(state.version)
|
|
167
176
|
);
|
|
@@ -359,7 +368,7 @@ function getPackagedFraimRuntimePath() {
|
|
|
359
368
|
return path_1.default.join(process.env.FRAIM_USER_DIR || path_1.default.join(os_1.default.homedir(), '.fraim'), 'bin', 'packaged-fraim-runtime.json');
|
|
360
369
|
}
|
|
361
370
|
function getFraimMcpLauncherStatePath() {
|
|
362
|
-
return path_1.default.join(process.env.FRAIM_USER_DIR || path_1.default.join(os_1.default.homedir(), '.fraim'), 'mcp-launcher', 'latest.json');
|
|
371
|
+
return path_1.default.join(process.env.FRAIM_USER_DIR || path_1.default.join(os_1.default.homedir(), '.fraim'), 'mcp-launcher', (0, user_config_1.getReleaseChannel)() === 'ppe' ? 'latest-next.json' : 'latest.json');
|
|
363
372
|
}
|
|
364
373
|
/**
|
|
365
374
|
* Record `version` as the version the launcher should run, resetting the freshness window.
|
|
@@ -394,6 +403,7 @@ function recordFraimMcpLauncherVersion(version, source = 'explicit-sync') {
|
|
|
394
403
|
binName: 'fraim',
|
|
395
404
|
version,
|
|
396
405
|
fromCache: false,
|
|
406
|
+
distTag: (0, user_config_1.getReleaseChannel)() === 'ppe' ? 'next' : 'latest',
|
|
397
407
|
launcherVersion: LAUNCHER_VERSION,
|
|
398
408
|
updatedAt: new Date().toISOString()
|
|
399
409
|
}, null, 2));
|
|
@@ -325,6 +325,15 @@ const GENERIC_WORKER_OWNED_JOBS = new Set([
|
|
|
325
325
|
// specialist hire, matching the existing no-employee attribution of adhoc runs.
|
|
326
326
|
exports.UNOWNED_EXEMPT_JOBS = new Set([
|
|
327
327
|
'adhoc-prompt',
|
|
328
|
+
// #2109: moving these existing operations into ai-employee folders does
|
|
329
|
+
// not change their prior null owner, attribution or ungated access.
|
|
330
|
+
'evolve-employee',
|
|
331
|
+
'graduate-job',
|
|
332
|
+
'generate-productivity-report',
|
|
333
|
+
'project-onboarding',
|
|
334
|
+
'sleep-on-learnings',
|
|
335
|
+
'share-with-others',
|
|
336
|
+
'video-demo-to-sop',
|
|
328
337
|
]);
|
|
329
338
|
function getPersonaCapabilityBundle(personaKey) {
|
|
330
339
|
return exports.PERSONA_CAPABILITY_BUNDLES[personaKey];
|
|
@@ -604,10 +604,7 @@ class FraimLocalMCPServer {
|
|
|
604
604
|
}
|
|
605
605
|
// Fallback to user config file
|
|
606
606
|
try {
|
|
607
|
-
const
|
|
608
|
-
if (!homeDir)
|
|
609
|
-
return '';
|
|
610
|
-
const configPath = (0, path_1.join)(homeDir, '.fraim', 'config.json');
|
|
607
|
+
const configPath = (0, path_1.join)((0, project_fraim_paths_1.getUserFraimDirPath)(), 'config.json');
|
|
611
608
|
if ((0, fs_1.existsSync)(configPath)) {
|
|
612
609
|
const config = JSON.parse((0, fs_1.readFileSync)(configPath, 'utf8'));
|
|
613
610
|
if (config.apiKey) {
|
|
@@ -628,10 +625,7 @@ class FraimLocalMCPServer {
|
|
|
628
625
|
if (process.env.FRAIM_RELEASE_CHANNEL)
|
|
629
626
|
return process.env.FRAIM_RELEASE_CHANNEL;
|
|
630
627
|
try {
|
|
631
|
-
const
|
|
632
|
-
if (!homeDir)
|
|
633
|
-
return '';
|
|
634
|
-
const config = JSON.parse((0, fs_1.readFileSync)((0, path_1.join)(homeDir, '.fraim', 'config.json'), 'utf8'));
|
|
628
|
+
const config = JSON.parse((0, fs_1.readFileSync)((0, path_1.join)((0, project_fraim_paths_1.getUserFraimDirPath)(), 'config.json'), 'utf8'));
|
|
635
629
|
if (config.releaseChannel)
|
|
636
630
|
return config.releaseChannel;
|
|
637
631
|
}
|
|
@@ -1203,8 +1197,7 @@ class FraimLocalMCPServer {
|
|
|
1203
1197
|
return this.config.workingStyle;
|
|
1204
1198
|
}
|
|
1205
1199
|
try {
|
|
1206
|
-
const
|
|
1207
|
-
const configPath = (0, path_1.join)(homeDir, '.fraim', 'config.json');
|
|
1200
|
+
const configPath = (0, path_1.join)((0, project_fraim_paths_1.getUserFraimDirPath)(), 'config.json');
|
|
1208
1201
|
if ((0, fs_1.existsSync)(configPath)) {
|
|
1209
1202
|
const config = JSON.parse((0, fs_1.readFileSync)(configPath, 'utf8'));
|
|
1210
1203
|
return config.workingStyle || 'PR';
|
|
@@ -1829,8 +1822,9 @@ class FraimLocalMCPServer {
|
|
|
1829
1822
|
return null;
|
|
1830
1823
|
// Read the job file so a domain it self-declares in frontmatter can override
|
|
1831
1824
|
// the category map (extensible for newly-taught jobs); the pure resolver
|
|
1832
|
-
// owns the decision logic.
|
|
1833
|
-
|
|
1825
|
+
// owns the decision logic. Display metadata would prepend an HTML comment
|
|
1826
|
+
// to personalized content, hiding its frontmatter from the domain parser.
|
|
1827
|
+
const resolved = await resolver.resolveFile(registryPath, { includeMetadata: false }).catch(() => null);
|
|
1834
1828
|
return (0, learning_domains_js_1.resolveDomainForJob)(registryPath, resolved?.content ?? null);
|
|
1835
1829
|
}
|
|
1836
1830
|
catch {
|