fraim 2.0.256 → 2.0.258

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.
@@ -243,7 +243,7 @@ const runSync = async (options) => {
243
243
  console.log(chalk_1.default.yellow(` ${rel}`));
244
244
  if (stranded.length > 10)
245
245
  console.log(chalk_1.default.yellow(` ...and ${stranded.length - 10} more`));
246
- console.log(chalk_1.default.yellow(`Move them into ${home.root} to make them live again. Nothing was deleted.`));
246
+ console.log(chalk_1.default.yellow(`Move them into ${home.contentRoot} to make them live again. Nothing was deleted.`));
247
247
  }
248
248
  }
249
249
  catch { /* reporting must never fail a sync */ }
@@ -287,7 +287,7 @@ const runSync = async (options) => {
287
287
  console.log(chalk_1.default.yellow(` ${rel}`));
288
288
  if (stranded.length > 10)
289
289
  console.log(chalk_1.default.yellow(` ...and ${stranded.length - 10} more`));
290
- console.log(chalk_1.default.yellow(`Move them into ${home.root} to make them live again. Nothing was deleted.`));
290
+ console.log(chalk_1.default.yellow(`Move them into ${home.contentRoot} to make them live again. Nothing was deleted.`));
291
291
  }
292
292
  }
293
293
  catch { /* reporting must never fail a sync */ }
@@ -40,7 +40,7 @@ const MANAGER_PACK_DIRS = ['context', 'rules', 'learnings', 'jobs', 'skills', 't
40
40
  * point at, so this now resolves the one place the layer lives.
41
41
  */
42
42
  function getManagerHomeDir() {
43
- return (0, pack_home_1.resolvePackHome)('manager').root;
43
+ return (0, pack_home_1.resolvePackHome)('manager').contentRoot;
44
44
  }
45
45
  /**
46
46
  * Where sync provenance is recorded.
@@ -43,16 +43,18 @@ async function publishManagerArtifacts(artifacts, opts) {
43
43
  }
44
44
  }
45
45
  if (managerStorage.backend === 'local-folder') {
46
- const localPath = managerStorage.localPath;
46
+ // Write into contentRoot (localPath/personalized-employee/) so the read
47
+ // side (packReadRoots -> contentRoot) sees the file immediately.
48
+ const contentRoot = (0, pack_home_1.resolvePackHome)('manager').contentRoot;
47
49
  const writtenPaths = [];
48
50
  for (const artifact of artifacts) {
49
- const result = (0, local_folder_sync_1.writeLocalFolderFile)(localPath, artifact.relativePath, artifact.content);
51
+ const result = (0, local_folder_sync_1.writeLocalFolderFile)(contentRoot, artifact.relativePath, artifact.content);
50
52
  if (result.skipped) {
51
53
  throw new Error(`Skipped writing '${artifact.relativePath}' to local folder: ${result.reason} Re-sync before publishing.`);
52
54
  }
53
- writtenPaths.push(path_1.default.join(localPath, artifact.relativePath));
55
+ writtenPaths.push(path_1.default.join(contentRoot, artifact.relativePath));
54
56
  }
55
- const deletedPaths = (0, local_folder_sync_1.removeLocalFolderFiles)(localPath, deletions, artifacts.map((a) => a.relativePath));
57
+ const deletedPaths = (0, local_folder_sync_1.removeLocalFolderFiles)(contentRoot, deletions, artifacts.map((a) => a.relativePath));
56
58
  return { backend: 'local-folder', writtenPaths, deletedPaths };
57
59
  }
58
60
  if (managerStorage.backend === 'fraim-cloud') {
@@ -80,7 +80,7 @@ function isSafeOrgCapabilityPackPath(relativePath) {
80
80
  * point at, so this now resolves the one place the layer lives.
81
81
  */
82
82
  function getOrgHomeDir() {
83
- return (0, pack_home_1.resolvePackHome)('org').root;
83
+ return (0, pack_home_1.resolvePackHome)('org').contentRoot;
84
84
  }
85
85
  /**
86
86
  * Where sync provenance is recorded.
@@ -78,16 +78,18 @@ async function publishOrgArtifacts(artifacts, opts) {
78
78
  throw new Error(`Invalid org-pack deletion path '${rel}'.`);
79
79
  }
80
80
  if (organization.backend === 'local-folder') {
81
- const localPath = organization.localPath;
81
+ // Write into contentRoot (localPath/personalized-employee/) so the read
82
+ // side (packReadRoots -> contentRoot) sees the file immediately.
83
+ const contentRoot = (0, pack_home_1.resolvePackHome)('org').contentRoot;
82
84
  const writtenPaths = [];
83
85
  for (const a of artifacts) {
84
- const result = (0, local_folder_sync_1.writeLocalFolderFile)(localPath, a.relativePath, a.content);
86
+ const result = (0, local_folder_sync_1.writeLocalFolderFile)(contentRoot, a.relativePath, a.content);
85
87
  if (result.skipped) {
86
88
  throw new Error(`Skipped writing '${a.relativePath}' to local folder: ${result.reason} Re-sync before publishing.`);
87
89
  }
88
- writtenPaths.push(path_1.default.join(localPath, a.relativePath));
90
+ writtenPaths.push(path_1.default.join(contentRoot, a.relativePath));
89
91
  }
90
- const deletedPaths = (0, local_folder_sync_1.removeLocalFolderFiles)(localPath, deletions, artifacts.map((a) => a.relativePath));
92
+ const deletedPaths = (0, local_folder_sync_1.removeLocalFolderFiles)(contentRoot, deletions, artifacts.map((a) => a.relativePath));
91
93
  return { backend: 'local-folder', writtenPaths, deletedPaths };
92
94
  }
93
95
  if (organization.backend === 'fraim-cloud') {
@@ -50,18 +50,52 @@ function packsDir() {
50
50
  return path_1.default.join((0, project_fraim_paths_1.getUserFraimDirPath)(), 'packs');
51
51
  }
52
52
  /**
53
- * The standard local home, used when the layer is not synced anywhere.
53
+ * The standard local home root (the pack repo root), used when the layer is not
54
+ * synced anywhere.
54
55
  *
55
- * Both layers keep their historical paths so existing machines need no
56
- * migration. Inventing a new location here would orphan content that is
57
- * already on disk: `~/.fraim/org/` has always been where org content lives,
58
- * and `~/.fraim/personalized-employee/` is where a manager authors.
56
+ * For manager: `~/.fraim/` capability content lives at
57
+ * `~/.fraim/personalized-employee/`, matching the project-level layout exactly.
58
+ * The historical on-disk path (`~/.fraim/personalized-employee/{stuff}`) is
59
+ * preserved via `contentRoot = join(root, 'personalized-employee')`.
60
+ *
61
+ * For org: `~/.fraim/org/` — capability content lives at
62
+ * `~/.fraim/org/personalized-employee/`. New installs land here automatically;
63
+ * existing installs with flat content at `~/.fraim/org/{stuff}` are migrated by
64
+ * `migrateOrgFlatContent`.
59
65
  */
60
66
  function standardHome(layer) {
61
67
  if (layer === 'manager')
62
- return path_1.default.join((0, project_fraim_paths_1.getUserFraimDirPath)(), 'personalized-employee');
68
+ return (0, project_fraim_paths_1.getUserFraimDirPath)();
63
69
  return path_1.default.join((0, project_fraim_paths_1.getUserFraimDirPath)(), 'org');
64
70
  }
71
+ /**
72
+ * Auto-migrate flat org content (pre-#1070 layout: `~/.fraim/org/{stuff}`)
73
+ * to the uniform subdir layout (`~/.fraim/org/personalized-employee/{stuff}`).
74
+ * Runs at most once per process per orgRoot path (guarded by a Set).
75
+ * Never throws: migration failures are silently skipped.
76
+ */
77
+ const _migratedOrgRoots = new Set();
78
+ const ORG_CONTENT_DIRS = ['context', 'rules', 'learnings', 'jobs', 'skills', 'templates', 'employees'];
79
+ function migrateOrgFlatContent(orgRoot) {
80
+ if (_migratedOrgRoots.has(orgRoot))
81
+ return;
82
+ _migratedOrgRoots.add(orgRoot);
83
+ const dest = path_1.default.join(orgRoot, 'personalized-employee');
84
+ try {
85
+ for (const dir of ORG_CONTENT_DIRS) {
86
+ const src = path_1.default.join(orgRoot, dir);
87
+ if (!fs_1.default.existsSync(src))
88
+ continue;
89
+ // Skip if already under personalized-employee.
90
+ const destDir = path_1.default.join(dest, dir);
91
+ if (fs_1.default.existsSync(destDir))
92
+ continue;
93
+ fs_1.default.mkdirSync(dest, { recursive: true });
94
+ fs_1.default.renameSync(src, destDir);
95
+ }
96
+ }
97
+ catch { /* migration is best-effort; never fail a read over it */ }
98
+ }
65
99
  /**
66
100
  * Where the cloud backend materializes. Also the historical path for each
67
101
  * layer, so switching to or from `fraim-cloud` does not relocate anything.
@@ -81,57 +115,52 @@ function defaultCloneDir(layer) {
81
115
  function resolvePackHome(layer) {
82
116
  const config = (0, user_config_1.getLayerBackend)(layer);
83
117
  const standard = standardHome(layer);
118
+ const make = (root, extra) => {
119
+ if (layer === 'org')
120
+ migrateOrgFlatContent(root);
121
+ return { layer, root, contentRoot: path_1.default.join(root, 'personalized-employee'), ...extra };
122
+ };
84
123
  if (!config || config.backend === 'single-machine') {
85
- return {
86
- layer,
124
+ return make(standard, {
87
125
  backend: config?.backend ?? 'single-machine',
88
- root: standard,
89
126
  synced: false,
90
127
  requiresPublish: false,
91
- };
128
+ });
92
129
  }
93
130
  if (config.backend === 'local-folder' && config.localPath) {
94
- return {
95
- layer,
131
+ return make(absolutize(config.localPath), {
96
132
  backend: 'local-folder',
97
- root: absolutize(config.localPath),
98
133
  synced: true,
99
134
  // The sync client replicates the write; there is nothing further to do.
100
135
  requiresPublish: false,
101
136
  legacyRoot: standard,
102
- };
137
+ });
103
138
  }
104
139
  if (config.backend === 'git' && config.gitUrl) {
105
- return {
106
- layer,
140
+ return make(config.localPath ? absolutize(config.localPath) : defaultCloneDir(layer), {
107
141
  backend: 'git',
108
- root: config.localPath ? absolutize(config.localPath) : defaultCloneDir(layer),
109
142
  synced: true,
110
143
  requiresPublish: true,
111
144
  gitUrl: config.gitUrl,
112
145
  legacyRoot: standard,
113
- };
146
+ });
114
147
  }
115
148
  if (config.backend === 'fraim-cloud') {
116
- return {
117
- layer,
149
+ return make(cloudHome(layer), {
118
150
  backend: 'fraim-cloud',
119
- root: cloudHome(layer),
120
151
  synced: true,
121
152
  requiresPublish: true,
122
153
  legacyRoot: standard,
123
- };
154
+ });
124
155
  }
125
156
  // A backend named but missing its required pointer (git without gitUrl,
126
157
  // local-folder without localPath). Fall back to the standard home rather
127
158
  // than inventing a location.
128
- return {
129
- layer,
159
+ return make(standard, {
130
160
  backend: config.backend,
131
- root: standard,
132
161
  synced: false,
133
162
  requiresPublish: false,
134
- };
163
+ });
135
164
  }
136
165
  /**
137
166
  * Where to read this layer from. Exactly one directory: the home.
@@ -141,7 +170,7 @@ function resolvePackHome(layer) {
141
170
  * entry again, the single-place invariant has been lost.
142
171
  */
143
172
  function packReadRoots(layer) {
144
- return [resolvePackHome(layer).root];
173
+ return [resolvePackHome(layer).contentRoot];
145
174
  }
146
175
  /**
147
176
  * Content sitting at the standard local path that the configured home does not
@@ -155,9 +184,12 @@ function packReadRoots(layer) {
155
184
  */
156
185
  function findStrandedLegacyContent(layer) {
157
186
  const home = resolvePackHome(layer);
158
- if (!home.legacyRoot || home.legacyRoot === home.root)
187
+ // legacyRoot is the old standard home root; stranded content is content that
188
+ // exists at the old location but not in the new contentRoot.
189
+ const legacyContentRoot = home.legacyRoot ? path_1.default.join(home.legacyRoot, 'personalized-employee') : null;
190
+ if (!legacyContentRoot || legacyContentRoot === home.contentRoot)
159
191
  return [];
160
- if (!fs_1.default.existsSync(home.legacyRoot))
192
+ if (!fs_1.default.existsSync(legacyContentRoot))
161
193
  return [];
162
194
  const stranded = [];
163
195
  const walk = (absDir, relDir) => {
@@ -173,11 +205,11 @@ function findStrandedLegacyContent(layer) {
173
205
  const abs = path_1.default.join(absDir, entry.name);
174
206
  if (entry.isDirectory())
175
207
  walk(abs, rel);
176
- else if (entry.isFile() && !fs_1.default.existsSync(path_1.default.join(home.root, rel)))
208
+ else if (entry.isFile() && !fs_1.default.existsSync(path_1.default.join(home.contentRoot, rel)))
177
209
  stranded.push(rel);
178
210
  }
179
211
  };
180
- walk(home.legacyRoot, '');
212
+ walk(legacyContentRoot, '');
181
213
  return stranded.sort();
182
214
  }
183
215
  const ALLOWED_GIT_URL = /^(https?:\/\/|ssh:\/\/|git:\/\/|file:\/\/|[\w.-]+@[\w.-]+:)/;
@@ -53,12 +53,13 @@ class LocalRegistryResolver {
53
53
  this.remoteContentResolver = options.remoteContentResolver;
54
54
  this.parser = new inheritance_parser_1.InheritanceParser(options.maxDepth);
55
55
  this.shouldFilter = options.shouldFilter;
56
- // Issue #1002: default the manager's writable home to ~/.fraim/personalized-employee/
56
+ // Issue #1002: default the manager's writable home to the configured contentRoot.
57
+ // contentRoot = join(resolvePackHome('manager').root, 'personalized-employee') for all backends.
57
58
  this.managerLocalRoot = options.managerLocalRoot ?? (0, path_1.join)((0, project_fraim_paths_1.getUserFraimDirPath)(), 'personalized-employee');
58
- // Issue #869: default manager cache root to ~/.fraim/manager/
59
- this.managerCacheRoot = options.managerCacheRoot ?? (0, path_1.join)((0, project_fraim_paths_1.getUserFraimDirPath)(), 'manager');
60
- // Issue #869 Phase 2: default org cache root to ~/.fraim/org/
61
- this.orgCacheRoot = options.orgCacheRoot ?? (0, path_1.join)((0, project_fraim_paths_1.getUserFraimDirPath)(), 'org');
59
+ // Issue #869 / #1070: default overlay roots to contentRoot (not the pack git root).
60
+ this.managerCacheRoot = options.managerCacheRoot ?? (0, path_1.join)((0, project_fraim_paths_1.getUserFraimDirPath)(), 'personalized-employee');
61
+ // Issue #869 Phase 2 / #1070: org contentRoot = ~/.fraim/org/personalized-employee/
62
+ this.orgCacheRoot = options.orgCacheRoot ?? (0, path_1.join)((0, project_fraim_paths_1.getUserFraimDirPath)(), 'org', 'personalized-employee');
62
63
  }
63
64
  /**
64
65
  * Get a path within the effective FRAIM directory.
@@ -65,16 +65,20 @@ function learningEntryHeadingRegex(flags = '') {
65
65
  function managerSecondaryLearningsBase() {
66
66
  const home = (0, pack_home_1.resolvePackHome)('manager');
67
67
  if (home.synced)
68
- return (0, path_1.join)(home.root, 'learnings');
68
+ return (0, path_1.join)(home.contentRoot, 'learnings');
69
69
  // pack-home-exempt: deliberate historical secondary location, see above.
70
70
  return (0, path_1.join)((0, project_fraim_paths_1.getUserFraimDirPath)(), 'manager', 'learnings');
71
71
  }
72
72
  function getLearningRoots(workspaceRoot) {
73
+ const managerHome = (0, pack_home_1.resolvePackHome)('manager');
74
+ const managerHomeBase = (0, path_1.join)(managerHome.contentRoot, 'learnings');
73
75
  return {
74
76
  globalPersonalBase: (0, project_fraim_paths_1.getConfiguredPortableLearningsDir)(workspaceRoot),
75
77
  globalPersonalDisplayBase: (0, project_fraim_paths_1.getConfiguredPortableLearningsDisplayPath)(workspaceRoot),
76
78
  managerCacheBase: managerSecondaryLearningsBase(),
77
79
  managerCacheDisplayBase: (0, project_fraim_paths_1.getUserFraimDisplayPath)('manager/learnings'),
80
+ managerHomeBase,
81
+ managerHomeDisplayBase: managerHomeBase.replace(/\\/g, '/'),
78
82
  repoLearningsBase: (0, project_fraim_paths_1.getWorkspaceLearningsDir)(workspaceRoot)
79
83
  };
80
84
  }
@@ -406,7 +410,7 @@ function resolveOrgLearningFile(repoLearningsBase, fileName) {
406
410
  if ((0, fs_1.existsSync)(repoPath)) {
407
411
  return { present: true, path: repoPath, displayPath: `${REPO_LEARNINGS_REL}/${fileName}` };
408
412
  }
409
- const cachePath = (0, path_1.join)((0, pack_home_1.resolvePackHome)('org').root, 'learnings', fileName);
413
+ const cachePath = (0, path_1.join)((0, pack_home_1.resolvePackHome)('org').contentRoot, 'learnings', fileName);
410
414
  if ((0, fs_1.existsSync)(cachePath)) {
411
415
  return { present: true, path: cachePath, displayPath: (0, project_fraim_paths_1.getUserFraimDisplayPath)(`org/learnings/${fileName}`) };
412
416
  }
@@ -419,7 +423,7 @@ function resolveOrgLearningFile(repoLearningsBase, fileName) {
419
423
  */
420
424
  function resolveOrgLearningFileTiers(repoLearningsBase, fileName) {
421
425
  const tiers = [];
422
- const cachePath = (0, path_1.join)((0, pack_home_1.resolvePackHome)('org').root, 'learnings', fileName);
426
+ const cachePath = (0, path_1.join)((0, pack_home_1.resolvePackHome)('org').contentRoot, 'learnings', fileName);
423
427
  if ((0, fs_1.existsSync)(cachePath)) {
424
428
  tiers.push({
425
429
  level: 'org',
@@ -624,7 +628,7 @@ function resolveOrgContextFile(workspaceRoot, relativePath, orgCacheEligible = t
624
628
  };
625
629
  }
626
630
  if (orgCacheEligible) {
627
- const cachePath = (0, path_1.join)((0, pack_home_1.resolvePackHome)('org').root, relativePath);
631
+ const cachePath = (0, path_1.join)((0, pack_home_1.resolvePackHome)('org').contentRoot, relativePath);
628
632
  if ((0, fs_1.existsSync)(cachePath)) {
629
633
  return {
630
634
  present: true,
@@ -633,7 +637,7 @@ function resolveOrgContextFile(workspaceRoot, relativePath, orgCacheEligible = t
633
637
  }
634
638
  }
635
639
  if (!orgCacheEligible) {
636
- const managerCachePath = (0, path_1.join)((0, pack_home_1.resolvePackHome)('manager').root, relativePath);
640
+ const managerCachePath = (0, path_1.join)((0, pack_home_1.resolvePackHome)('manager').contentRoot, relativePath);
637
641
  if ((0, fs_1.existsSync)(managerCachePath)) {
638
642
  return {
639
643
  present: true,
@@ -795,7 +799,7 @@ function resolveTeamContextFile(workspaceRoot, key) {
795
799
  // destination (R5.1), so writePath stays empty and the caller must route
796
800
  // edits through the org backend's propose-and-approve flow.
797
801
  if (key === 'org' || key === 'orgRules') {
798
- const cachePath = (0, path_1.join)((0, pack_home_1.resolvePackHome)('org').root, relativePath);
802
+ const cachePath = (0, path_1.join)((0, pack_home_1.resolvePackHome)('org').contentRoot, relativePath);
799
803
  if ((0, fs_1.existsSync)(cachePath)) {
800
804
  return {
801
805
  present: true,
@@ -808,7 +812,7 @@ function resolveTeamContextFile(workspaceRoot, key) {
808
812
  }
809
813
  }
810
814
  if (key === 'manager' || key === 'managerRules') {
811
- const managerCachePath = (0, path_1.join)((0, pack_home_1.resolvePackHome)('manager').root, relativePath);
815
+ const managerCachePath = (0, path_1.join)((0, pack_home_1.resolvePackHome)('manager').contentRoot, relativePath);
812
816
  if ((0, fs_1.existsSync)(managerCachePath)) {
813
817
  return {
814
818
  present: true,
@@ -845,7 +849,7 @@ function resolveTeamContextFile(workspaceRoot, key) {
845
849
  function orgBrandCandidateDirs(workspaceRoot) {
846
850
  return [
847
851
  (0, path_1.join)((0, project_fraim_paths_1.getWorkspaceFraimDir)(workspaceRoot), 'personalized-employee', 'context'),
848
- (0, path_1.join)((0, pack_home_1.resolvePackHome)('org').root, 'context'),
852
+ (0, path_1.join)((0, pack_home_1.resolvePackHome)('org').contentRoot, 'context'),
849
853
  (0, path_1.join)((0, project_fraim_paths_1.getUserFraimDirPath)(), 'personalized-employee', 'context'),
850
854
  ];
851
855
  }
@@ -1224,7 +1228,9 @@ function parseLearningEntries(filePath, displayPath, category, level, domain = '
1224
1228
  }
1225
1229
  function levelDir(roots, level) {
1226
1230
  if (level === 'machine') {
1227
- return { dir: roots.globalPersonalBase, displayBase: roots.globalPersonalDisplayBase.replace(/\/$/, '') };
1231
+ // Issue #1070: use the configured manager home, not the portable authoring base.
1232
+ // For single-machine backends managerHomeBase == globalPersonalBase (no change).
1233
+ return { dir: roots.managerHomeBase, displayBase: roots.managerHomeDisplayBase.replace(/\/$/, '') };
1228
1234
  }
1229
1235
  return { dir: roots.repoLearningsBase, displayBase: REPO_LEARNINGS_REL };
1230
1236
  }
@@ -1268,7 +1274,8 @@ function resolveLearningFilePath(workspaceRoot, userId, ref) {
1268
1274
  if (ref.scope === 'org')
1269
1275
  return (0, path_1.join)(roots.repoLearningsBase, `org-${fileType}.md`);
1270
1276
  const resolvedUserId = resolveLearningUserId(workspaceRoot, userId, roots);
1271
- const base = ref.level === 'project' ? roots.repoLearningsBase : roots.globalPersonalBase;
1277
+ // Issue #1070: for the 'machine' level use the configured manager home.
1278
+ const base = ref.level === 'project' ? roots.repoLearningsBase : roots.managerHomeBase;
1272
1279
  return (0, path_1.join)(base, `${resolvedUserId}-${fileType}.md`);
1273
1280
  }
1274
1281
  function titleCaseFromFileType(fileType) {
@@ -1591,8 +1591,8 @@ class FraimLocalMCPServer {
1591
1591
  workspaceRoot: process.cwd(),
1592
1592
  // Issue #1043 round 2: overlay roots are the layers' homes. There is no
1593
1593
  // separate cache to point at any more.
1594
- managerCacheRoot: (0, pack_home_1.resolvePackHome)('manager').root,
1595
- orgCacheRoot: (0, pack_home_1.resolvePackHome)('org').root,
1594
+ managerCacheRoot: (0, pack_home_1.resolvePackHome)('manager').contentRoot,
1595
+ orgCacheRoot: (0, pack_home_1.resolvePackHome)('org').contentRoot,
1596
1596
  remoteContentResolver: async (_path) => {
1597
1597
  throw new Error('No project root available');
1598
1598
  },
@@ -1610,8 +1610,8 @@ class FraimLocalMCPServer {
1610
1610
  workspaceRoot,
1611
1611
  ...(needsEffectiveDirOverride ? { effectiveFraimDir } : {}),
1612
1612
  // Issue #1043 round 2: overlay roots are the layers' homes.
1613
- managerCacheRoot: (0, pack_home_1.resolvePackHome)('manager').root,
1614
- orgCacheRoot: (0, pack_home_1.resolvePackHome)('org').root,
1613
+ managerCacheRoot: (0, pack_home_1.resolvePackHome)('manager').contentRoot,
1614
+ orgCacheRoot: (0, pack_home_1.resolvePackHome)('org').contentRoot,
1615
1615
  shouldFilter: (content) => this.isStub(content),
1616
1616
  remoteContentResolver: async (path) => {
1617
1617
  // Fetch parent content from remote for inheritance
@@ -2234,11 +2234,10 @@ class FraimLocalMCPServer {
2234
2234
  // from every project, so omitting it here made it invisible in the
2235
2235
  // one place the manager looks to find out what their employee can do.
2236
2236
  // Lowest precedence first, so a project job of the same name wins.
2237
- const { getUserFraimDirPath } = require('../core/utils/project-fraim-paths');
2238
- const userFraimDir = getUserFraimDirPath();
2237
+ const { resolvePackHome: _resolvePackHome } = require('../cli/utils/pack-home');
2238
+ const managerJobsDir = (0, path_1.join)(_resolvePackHome('manager').contentRoot, 'jobs');
2239
2239
  const jobDirsByLevel = [
2240
- { dir: (0, path_1.join)(userFraimDir, 'manager', 'jobs'), level: 'manager' },
2241
- { dir: (0, path_1.join)(userFraimDir, 'personalized-employee', 'jobs'), level: 'manager' },
2240
+ { dir: managerJobsDir, level: 'manager' },
2242
2241
  ...(projectRoot
2243
2242
  ? [{ dir: (0, path_1.join)(projectRoot, 'fraim', 'personalized-employee', 'jobs'), level: 'project' }]
2244
2243
  : []),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fraim",
3
- "version": "2.0.256",
3
+ "version": "2.0.258",
4
4
  "description": "FRAIM core CLI and MCP package.",
5
5
  "main": "index.js",
6
6
  "bin": {