fraim 2.0.167 → 2.0.168

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.
Files changed (54) hide show
  1. package/dist/src/ai-hub/catalog.js +28 -14
  2. package/dist/src/ai-hub/server.js +10 -403
  3. package/dist/src/cli/commands/init-project.js +1 -98
  4. package/dist/src/cli/commands/manager.js +40 -0
  5. package/dist/src/cli/commands/sync.js +17 -21
  6. package/dist/src/cli/fraim.js +2 -0
  7. package/dist/src/cli/utils/github-workflow-sync.js +12 -146
  8. package/dist/src/cli/utils/manager-pack-sync.js +188 -0
  9. package/dist/src/cli/utils/manager-publish.js +76 -0
  10. package/dist/src/cli/utils/user-config.js +20 -0
  11. package/dist/src/core/fraim-config-schema.generated.js +85 -10
  12. package/dist/src/core/manager-pack.js +26 -0
  13. package/dist/src/first-run/install-state.js +1 -0
  14. package/dist/src/first-run/server.js +9 -0
  15. package/dist/src/first-run/session-service.js +117 -23
  16. package/dist/src/first-run/types.js +2 -5
  17. package/dist/src/local-mcp-server/learning-context-builder.js +45 -8
  18. package/dist/src/local-mcp-server/stdio-server.js +28 -0
  19. package/index.js +1 -1
  20. package/package.json +1 -2
  21. package/public/ai-hub/index.html +0 -81
  22. package/public/ai-hub/powerpoint-taskpane/index.html +236 -236
  23. package/public/ai-hub/powerpoint-taskpane/manifest.xml +29 -29
  24. package/public/ai-hub/script.js +3 -219
  25. package/public/ai-hub/styles.css +8 -36
  26. package/public/first-run/index.html +1 -1
  27. package/public/first-run/script.js +459 -530
  28. package/public/first-run/styles.css +288 -73
  29. package/public/portfolio/ashley.html +1 -1
  30. package/public/portfolio/casey.html +1 -1
  31. package/public/portfolio/celia.html +1 -1
  32. package/public/portfolio/gautam.html +1 -1
  33. package/public/portfolio/hari.html +1 -1
  34. package/public/portfolio/maestro.html +1 -1
  35. package/public/portfolio/mandy.html +1 -1
  36. package/public/portfolio/pam.html +6 -6
  37. package/public/portfolio/qasm.html +1 -1
  38. package/public/portfolio/sade.html +1 -1
  39. package/public/portfolio/sam.html +1 -1
  40. package/public/portfolio/swen.html +6 -6
  41. package/dist/src/ai-hub/word-sideload.js +0 -95
  42. package/dist/src/cli/commands/test-mcp.js +0 -171
  43. package/dist/src/cli/setup/first-run.js +0 -242
  44. package/dist/src/config/ai-manager-hiring.js +0 -121
  45. package/dist/src/config/compat.js +0 -16
  46. package/dist/src/config/feature-flags.js +0 -25
  47. package/dist/src/config/persona-capability-bundles.js +0 -273
  48. package/dist/src/config/persona-hiring.js +0 -270
  49. package/dist/src/config/portfolio-slug-overrides.js +0 -17
  50. package/dist/src/config/pricing.js +0 -37
  51. package/dist/src/config/stripe.js +0 -43
  52. package/dist/src/core/config-writer.js +0 -75
  53. package/dist/src/core/utils/job-aliases.js +0 -47
  54. package/dist/src/core/utils/workflow-parser.js +0 -174
@@ -47,10 +47,12 @@ function getLearningRoots(workspaceRoot) {
47
47
  return {
48
48
  globalPersonalBase: (0, project_fraim_paths_1.getConfiguredPortableLearningsDir)(workspaceRoot),
49
49
  globalPersonalDisplayBase: (0, project_fraim_paths_1.getConfiguredPortableLearningsDisplayPath)(workspaceRoot),
50
+ managerCacheBase: (0, path_1.join)((0, project_fraim_paths_1.getUserFraimDirPath)(), 'manager', 'learnings'),
51
+ managerCacheDisplayBase: (0, project_fraim_paths_1.getUserFraimDisplayPath)('manager/learnings'),
50
52
  repoLearningsBase: (0, project_fraim_paths_1.getWorkspaceLearningsDir)(workspaceRoot)
51
53
  };
52
54
  }
53
- function resolvePersonalLearningFile(repoBase, globalBase, globalDisplayBase, fileName) {
55
+ function resolvePersonalLearningFile(repoBase, managerCacheBase, managerCacheDisplayBase, globalBase, globalDisplayBase, fileName) {
54
56
  const repoPath = (0, path_1.join)(repoBase, fileName);
55
57
  if ((0, fs_1.existsSync)(repoPath)) {
56
58
  return {
@@ -67,6 +69,14 @@ function resolvePersonalLearningFile(repoBase, globalBase, globalDisplayBase, fi
67
69
  displayPath: `${globalDisplayBase.replace(/\/$/, '')}/${fileName}`
68
70
  };
69
71
  }
72
+ const managerCachePath = (0, path_1.join)(managerCacheBase, fileName);
73
+ if ((0, fs_1.existsSync)(managerCachePath)) {
74
+ return {
75
+ present: true,
76
+ path: managerCachePath,
77
+ displayPath: `${managerCacheDisplayBase.replace(/\/$/, '')}/${fileName}`
78
+ };
79
+ }
70
80
  return { present: false, path: globalPath, displayPath: `${globalDisplayBase.replace(/\/$/, '')}/${fileName}` };
71
81
  }
72
82
  function buildUserIdCandidates(userId) {
@@ -132,6 +142,10 @@ function resolveLearningUserId(workspaceRoot, userId, roots) {
132
142
  ((0, fs_1.existsSync)((0, path_1.join)(roots.globalPersonalBase, `${candidate}-manager-coaching.md`)) ? 1 : 0) +
133
143
  ((0, fs_1.existsSync)((0, path_1.join)(roots.globalPersonalBase, `${candidate}-mistake-patterns.md`)) ? 1 : 0) +
134
144
  ((0, fs_1.existsSync)((0, path_1.join)(roots.globalPersonalBase, `${candidate}-validated-patterns.md`)) ? 1 : 0) +
145
+ ((0, fs_1.existsSync)((0, path_1.join)(roots.managerCacheBase, `${candidate}-preferences.md`)) ? 1 : 0) +
146
+ ((0, fs_1.existsSync)((0, path_1.join)(roots.managerCacheBase, `${candidate}-manager-coaching.md`)) ? 1 : 0) +
147
+ ((0, fs_1.existsSync)((0, path_1.join)(roots.managerCacheBase, `${candidate}-mistake-patterns.md`)) ? 1 : 0) +
148
+ ((0, fs_1.existsSync)((0, path_1.join)(roots.managerCacheBase, `${candidate}-validated-patterns.md`)) ? 1 : 0) +
135
149
  ((0, fs_1.existsSync)((0, path_1.join)(roots.repoLearningsBase, `${candidate}-preferences.md`)) ? 1 : 0) +
136
150
  ((0, fs_1.existsSync)((0, path_1.join)(roots.repoLearningsBase, `${candidate}-manager-coaching.md`)) ? 1 : 0) +
137
151
  ((0, fs_1.existsSync)((0, path_1.join)(roots.repoLearningsBase, `${candidate}-mistake-patterns.md`)) ? 1 : 0) +
@@ -145,7 +159,7 @@ function resolveLearningUserId(workspaceRoot, userId, roots) {
145
159
  }
146
160
  if (bestScore > 0)
147
161
  return bestCandidate;
148
- const availablePrefixes = collectAvailableUserPrefixes(workspaceRoot, [roots.repoLearningsBase, roots.globalPersonalBase]);
162
+ const availablePrefixes = collectAvailableUserPrefixes(workspaceRoot, [roots.repoLearningsBase, roots.managerCacheBase, roots.globalPersonalBase]);
149
163
  if (availablePrefixes.size === 1) {
150
164
  return Array.from(availablePrefixes)[0];
151
165
  }
@@ -375,10 +389,10 @@ function buildLearningContextSection(workspaceRoot, userId, forJob) {
375
389
  const l2ValidatedPresent = l2Validated.present;
376
390
  const l2MistakeStats = l2MistakePresent ? scanMistakePatternFile(l2Mistake.path, threshold, 'mistake-patterns') : null;
377
391
  const l2ValidatedStats = l2ValidatedPresent ? scanMistakePatternFile(l2Validated.path, threshold, 'validated-patterns') : null;
378
- const l1Mistake = resolvePersonalLearningFile(roots.repoLearningsBase, roots.globalPersonalBase, roots.globalPersonalDisplayBase, `${resolvedUserId}-mistake-patterns.md`);
379
- const l1Pref = resolvePersonalLearningFile(roots.repoLearningsBase, roots.globalPersonalBase, roots.globalPersonalDisplayBase, `${resolvedUserId}-preferences.md`);
380
- const l1Coach = resolvePersonalLearningFile(roots.repoLearningsBase, roots.globalPersonalBase, roots.globalPersonalDisplayBase, `${resolvedUserId}-manager-coaching.md`);
381
- const l1Validated = resolvePersonalLearningFile(roots.repoLearningsBase, roots.globalPersonalBase, roots.globalPersonalDisplayBase, `${resolvedUserId}-validated-patterns.md`);
392
+ const l1Mistake = resolvePersonalLearningFile(roots.repoLearningsBase, roots.managerCacheBase, roots.managerCacheDisplayBase, roots.globalPersonalBase, roots.globalPersonalDisplayBase, `${resolvedUserId}-mistake-patterns.md`);
393
+ const l1Pref = resolvePersonalLearningFile(roots.repoLearningsBase, roots.managerCacheBase, roots.managerCacheDisplayBase, roots.globalPersonalBase, roots.globalPersonalDisplayBase, `${resolvedUserId}-preferences.md`);
394
+ const l1Coach = resolvePersonalLearningFile(roots.repoLearningsBase, roots.managerCacheBase, roots.managerCacheDisplayBase, roots.globalPersonalBase, roots.globalPersonalDisplayBase, `${resolvedUserId}-manager-coaching.md`);
395
+ const l1Validated = resolvePersonalLearningFile(roots.repoLearningsBase, roots.managerCacheBase, roots.managerCacheDisplayBase, roots.globalPersonalBase, roots.globalPersonalDisplayBase, `${resolvedUserId}-validated-patterns.md`);
382
396
  const l1MistakeStats = l1Mistake.present ? scanMistakePatternFile(l1Mistake.path, threshold, 'mistake-patterns') : null;
383
397
  const l1ValidatedStats = l1Validated.present ? scanMistakePatternFile(l1Validated.path, threshold, 'validated-patterns') : null;
384
398
  let l0CoachingCount = 0;
@@ -509,6 +523,15 @@ function resolveOrgContextFile(workspaceRoot, relativePath, orgCacheEligible = t
509
523
  };
510
524
  }
511
525
  }
526
+ if (!orgCacheEligible) {
527
+ const managerCachePath = (0, path_1.join)((0, project_fraim_paths_1.getUserFraimDirPath)(), 'manager', relativePath);
528
+ if ((0, fs_1.existsSync)(managerCachePath)) {
529
+ return {
530
+ present: true,
531
+ displayPath: (0, project_fraim_paths_1.getUserFraimDisplayPath)(`manager/${relativePath}`)
532
+ };
533
+ }
534
+ }
512
535
  const userPath = (0, path_1.join)((0, project_fraim_paths_1.getUserFraimDirPath)(), 'personalized-employee', relativePath);
513
536
  if ((0, fs_1.existsSync)(userPath)) {
514
537
  return {
@@ -675,6 +698,19 @@ function resolveTeamContextFile(workspaceRoot, key) {
675
698
  };
676
699
  }
677
700
  }
701
+ if (key === 'manager' || key === 'managerRules') {
702
+ const managerCachePath = (0, path_1.join)((0, project_fraim_paths_1.getUserFraimDirPath)(), 'manager', relativePath);
703
+ if ((0, fs_1.existsSync)(managerCachePath)) {
704
+ return {
705
+ present: true,
706
+ readPath: managerCachePath,
707
+ writePath: '',
708
+ displayPath: (0, project_fraim_paths_1.getUserFraimDisplayPath)(`manager/${relativePath}`),
709
+ scope,
710
+ managedByManagerSync: true
711
+ };
712
+ }
713
+ }
678
714
  const userPath = (0, path_1.join)((0, project_fraim_paths_1.getUserFraimDirPath)(), 'personalized-employee', relativePath);
679
715
  const userDisplay = (0, project_fraim_paths_1.getUserFraimDisplayPath)(`personalized-employee/${relativePath}`);
680
716
  return {
@@ -728,7 +764,7 @@ function countPreservedLearnings(workspaceRoot, userId) {
728
764
  countLearningEntries(resolveOrgLearningFile(roots.repoLearningsBase, 'org-preferences.md').path) +
729
765
  countLearningEntries(resolveOrgLearningFile(roots.repoLearningsBase, 'org-manager-coaching.md').path) +
730
766
  countLearningEntries(resolveOrgLearningFile(roots.repoLearningsBase, 'org-validated-patterns.md').path);
731
- const resolve = (fileName) => resolvePersonalLearningFile(roots.repoLearningsBase, roots.globalPersonalBase, roots.globalPersonalDisplayBase, fileName);
767
+ const resolve = (fileName) => resolvePersonalLearningFile(roots.repoLearningsBase, roots.managerCacheBase, roots.managerCacheDisplayBase, roots.globalPersonalBase, roots.globalPersonalDisplayBase, fileName);
732
768
  // L1 manager-facing reverse-mentoring file.
733
769
  const manager = countLearningEntries(resolve(`${resolvedUserId}-manager-coaching.md`).path);
734
770
  // L1 personal work patterns (project scope).
@@ -818,8 +854,9 @@ function parseLearningEntries(filePath, displayPath, category, level) {
818
854
  return out;
819
855
  }
820
856
  function levelDir(roots, level) {
821
- if (level === 'machine')
857
+ if (level === 'machine') {
822
858
  return { dir: roots.globalPersonalBase, displayBase: roots.globalPersonalDisplayBase.replace(/\/$/, '') };
859
+ }
823
860
  return { dir: roots.repoLearningsBase, displayBase: REPO_LEARNINGS_REL };
824
861
  }
825
862
  function readPreservedLearnings(workspaceRoot, userId, scope, level = 'machine') {
@@ -416,6 +416,7 @@ class FraimLocalMCPServer {
416
416
  this.connectSyncInFlight = null;
417
417
  this.latestConnectSyncWarning = null;
418
418
  this.orgCacheRefreshInFlight = false;
419
+ this.managerCacheRefreshInFlight = false;
419
420
  this.writer = writer || process.stdout.write.bind(process.stdout);
420
421
  this.remoteUrl = process.env.FRAIM_REMOTE_URL || 'https://fraim.wellnessatwork.me';
421
422
  this.apiKey = this.loadApiKey();
@@ -750,6 +751,7 @@ class FraimLocalMCPServer {
750
751
  this.connectSyncInFlight = null;
751
752
  }
752
753
  this.maybeRefreshOrgCache(String(requestId));
754
+ this.maybeRefreshManagerCache(String(requestId));
753
755
  }
754
756
  /**
755
757
  * Issue #563 (R4.2): opportunistically refresh the managed org cache
@@ -779,6 +781,32 @@ class FraimLocalMCPServer {
779
781
  this.orgCacheRefreshInFlight = false;
780
782
  });
781
783
  }
784
+ /**
785
+ * Issue #580: opportunistically refresh the managed manager cache
786
+ * (~/.fraim/manager/) at session bootstrap when it is missing or older than
787
+ * 24 hours. Fire-and-forget; a failed refresh leaves existing cache available.
788
+ */
789
+ maybeRefreshManagerCache(requestId) {
790
+ if (this.managerCacheRefreshInFlight)
791
+ return;
792
+ this.managerCacheRefreshInFlight = true;
793
+ void Promise.resolve().then(() => __importStar(require('../cli/utils/manager-pack-sync'))).then(async ({ getManagerCacheAgeHours, syncManagerCache }) => {
794
+ const ageHours = getManagerCacheAgeHours();
795
+ if (ageHours !== null && ageHours < 24)
796
+ return;
797
+ const outcome = await syncManagerCache();
798
+ if (outcome.status !== 'disabled') {
799
+ const version = outcome.metadata ? ` (version ${outcome.metadata.version.slice(0, 12)})` : '';
800
+ this.log(`[req:${requestId}] Manager cache refresh at connect: ${outcome.status}${version}`);
801
+ }
802
+ })
803
+ .catch((error) => {
804
+ this.logError(`[req:${requestId}] Manager cache refresh failed: ${error?.message || error}`);
805
+ })
806
+ .finally(() => {
807
+ this.managerCacheRefreshInFlight = false;
808
+ });
809
+ }
782
810
  /**
783
811
  * Automatically detect machine information
784
812
  */
package/index.js CHANGED
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env node
2
2
 
3
3
  /**
4
4
  * FRAIM Framework - Smart Entry Point
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fraim",
3
- "version": "2.0.167",
3
+ "version": "2.0.168",
4
4
  "description": "FRAIM CLI - Framework for Rigor-based AI Management (alias for fraim-framework)",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -122,7 +122,6 @@
122
122
  "dist/src/ai-hub/",
123
123
  "dist/src/first-run/",
124
124
  "dist/src/core/",
125
- "dist/src/config/",
126
125
  "bin/fraim.js",
127
126
  "bin/fraim-mcp.js",
128
127
  "public/ai-hub/",
@@ -194,18 +194,6 @@
194
194
  <span class="ca-note">— from <strong>sleep-on-learnings</strong> · promote to a scope</span></summary>
195
195
  <div class="ctx-acc-body"><div id="project-learnings"></div></div>
196
196
  </details>
197
- <!-- Issue #578: Scheduled + Reactive Employees — deployment roster -->
198
- <details class="ctx-acc" id="proj-deployments-acc">
199
- <summary><span class="ca-chev">▸</span> <span>⏱ Deployments</span>
200
- <span class="ca-note">— scheduled and webhook triggers for this project</span></summary>
201
- <div class="ctx-acc-body">
202
- <div id="proj-deployments-list"></div>
203
- <div class="dep-actions">
204
- <button class="dep-add-btn" id="dep-add-schedule-btn" type="button">+ Schedule</button>
205
- <button class="dep-add-btn" id="dep-add-webhook-btn" type="button">+ Webhook</button>
206
- </div>
207
- </div>
208
- </details>
209
197
  </div>
210
198
 
211
199
 
@@ -680,75 +668,6 @@
680
668
  </div>
681
669
  </div>
682
670
 
683
- <!-- Issue #578: Add Schedule deployment modal -->
684
- <div id="dep-schedule-modal" class="modal-overlay" hidden>
685
- <div class="modal-card" style="max-width:480px;">
686
- <div class="modal-hdr">
687
- <button class="modal-close" id="dep-schedule-close" type="button" aria-label="Close">×</button>
688
- <h2>New Scheduled Deployment</h2>
689
- </div>
690
- <div class="modal-body">
691
- <div class="hm-field">
692
- <label for="dep-sch-label">Label</label>
693
- <input type="text" id="dep-sch-label" placeholder="e.g. Nightly standup" />
694
- </div>
695
- <div class="hm-field">
696
- <label for="dep-sch-job">Job</label>
697
- <select id="dep-sch-job"></select>
698
- </div>
699
- <div class="hm-field">
700
- <label for="dep-sch-cron">Cron expression</label>
701
- <input type="text" id="dep-sch-cron" placeholder="e.g. 0 9 * * 1-5 (9am Mon-Fri)" />
702
- </div>
703
- <div class="hm-field">
704
- <label for="dep-sch-instructions">Initial instructions (optional)</label>
705
- <textarea id="dep-sch-instructions" rows="2" placeholder="Optional coaching message to send at run start"></textarea>
706
- </div>
707
- <div class="dep-modal-actions">
708
- <button type="button" id="dep-sch-save-btn" class="send-button">Create schedule</button>
709
- <button type="button" id="dep-sch-cancel-btn" class="cancel-button">Cancel</button>
710
- </div>
711
- <p id="dep-sch-error" class="dep-error" hidden></p>
712
- </div>
713
- </div>
714
- </div>
715
-
716
- <!-- Issue #578: Add Webhook deployment modal -->
717
- <div id="dep-webhook-modal" class="modal-overlay" hidden>
718
- <div class="modal-card" style="max-width:480px;">
719
- <div class="modal-hdr">
720
- <button class="modal-close" id="dep-webhook-close" type="button" aria-label="Close">×</button>
721
- <h2>New Webhook Deployment</h2>
722
- </div>
723
- <div class="modal-body">
724
- <div class="hm-field">
725
- <label for="dep-wh-label">Label</label>
726
- <input type="text" id="dep-wh-label" placeholder="e.g. ServiceNow escalation" />
727
- </div>
728
- <div class="hm-field">
729
- <label for="dep-wh-job">Job</label>
730
- <select id="dep-wh-job"></select>
731
- </div>
732
- <div class="hm-field">
733
- <label for="dep-wh-instructions">Initial instructions (optional)</label>
734
- <textarea id="dep-wh-instructions" rows="2" placeholder="Optional coaching message to prepend at run start"></textarea>
735
- </div>
736
- <div class="dep-modal-actions">
737
- <button type="button" id="dep-wh-save-btn" class="send-button">Create webhook</button>
738
- <button type="button" id="dep-wh-cancel-btn" class="cancel-button">Cancel</button>
739
- </div>
740
- <p id="dep-wh-error" class="dep-error" hidden></p>
741
- <div id="dep-wh-inbound-row" hidden>
742
- <label>Inbound URL (copy to your system)</label>
743
- <div class="dep-inbound-url-row">
744
- <code id="dep-wh-inbound-url" class="dep-inbound-url"></code>
745
- <button type="button" id="dep-wh-copy-btn" class="hm-copy-btn">Copy</button>
746
- </div>
747
- </div>
748
- </div>
749
- </div>
750
- </div>
751
-
752
671
  <!-- Issue #539: Command palette overlay — replaces 2-step modal as job-launch surface -->
753
672
  <div id="cp-modal" class="cp-backdrop" role="dialog" aria-modal="true" aria-label="Start a job" hidden>
754
673
  <div class="cp-palette">