fraim 2.0.169 → 2.0.170

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.
@@ -59,6 +59,7 @@ const conversation_store_1 = require("./conversation-store");
59
59
  const managed_browser_1 = require("./managed-browser");
60
60
  const managed_agent_paths_1 = require("../cli/utils/managed-agent-paths");
61
61
  let personaHiringModule;
62
+ let managerHiringModule;
62
63
  function loadPersonaHiringModule() {
63
64
  const cached = personaHiringModule;
64
65
  if (cached !== undefined) {
@@ -77,6 +78,24 @@ function loadPersonaHiringModule() {
77
78
  return null;
78
79
  }
79
80
  }
81
+ function loadManagerHiringModule() {
82
+ const cached = managerHiringModule;
83
+ if (cached !== undefined) {
84
+ return cached;
85
+ }
86
+ try {
87
+ // Server deployments include the manager-hiring catalog. The npm client
88
+ // package intentionally does not, so Hub bootstrap must not require it.
89
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
90
+ const loaded = require('../config/ai-manager-hiring');
91
+ managerHiringModule = loaded;
92
+ return loaded;
93
+ }
94
+ catch {
95
+ managerHiringModule = null;
96
+ return null;
97
+ }
98
+ }
80
99
  function loadPersonaCapabilityModule() {
81
100
  try {
82
101
  // Server deployments include the persona catalog. The npm client package
@@ -101,6 +120,13 @@ function buildHubPersonaHireUrl(personaKey, hireMode = 'job') {
101
120
  function buildHubPersonaAvatarUrl(personaKey) {
102
121
  return loadPersonaHiringModule()?.buildPersonaAvatarUrl(personaKey) ?? '';
103
122
  }
123
+ function buildHubManagerHiringCatalog() {
124
+ return loadManagerHiringModule()?.buildManagerHiringCatalog() ?? {
125
+ qualities: [],
126
+ services: [],
127
+ roles: {},
128
+ };
129
+ }
104
130
  async function getHubWorkspacePersonaState(dbService, userId, apiKey) {
105
131
  try {
106
132
  // eslint-disable-next-line @typescript-eslint/no-var-requires
@@ -1037,7 +1063,7 @@ class AiHubServer {
1037
1063
  // Issue #538 — source of truth for the "Hire a human manager" UI. Lazy-required
1038
1064
  // (not a top-level import) so the lightweight client CLI paths that import this
1039
1065
  // module for findAvailablePort do not eagerly load server-only config (repro #422).
1040
- managerHiring: require('../config/ai-manager-hiring').buildManagerHiringCatalog(),
1066
+ managerHiring: buildHubManagerHiringCatalog(),
1041
1067
  // Issue #540: server-authoritative manager team (personas assigned by this manager).
1042
1068
  managerTeam,
1043
1069
  };
@@ -187,6 +187,11 @@ class InheritanceParser {
187
187
  const parentMeta = JSON.parse(parentMatch[1]);
188
188
  const mergedMeta = { ...parentMeta, ...childMeta };
189
189
  delete mergedMeta.extends; // Remove extends from final merged content
190
+ // Deep-merge phase routing so child only overrides the entries it specifies;
191
+ // parent routing for untouched phases flows through unchanged.
192
+ if (parentMeta.phases && childMeta.phases) {
193
+ mergedMeta.phases = { ...parentMeta.phases, ...childMeta.phases };
194
+ }
190
195
  // 2. Extract Body (everything after frontmatter)
191
196
  const childBody = this.stripRedundantParentImports(child.substring(childMatch[0].length).trim(), typeof childMeta.extends === 'string' ? childMeta.extends : undefined);
192
197
  const parentBody = parent.substring(parentMatch[0].length).trim();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fraim",
3
- "version": "2.0.169",
3
+ "version": "2.0.170",
4
4
  "description": "FRAIM CLI - Framework for Rigor-based AI Management (alias for fraim-framework)",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -3976,11 +3976,14 @@ async function startRun(job, instructions, employeeId, preassignedConvId) {
3976
3976
  // Issue #489: capture selection state at job-start so write-back knows insert-after vs append.
3977
3977
  wordStartedWithSelection: document.body.dataset.surface === 'task-pane' && !!(state.wordContext && state.wordContext.hasSelection),
3978
3978
  };
3979
- upsertConversation(conv);
3980
- state.activeId = conv.id;
3981
- persistConversations();
3982
- renderRail();
3983
- renderActive();
3979
+ upsertConversation(conv);
3980
+ state.activeId = conv.id;
3981
+ // Issue #539: make Cmd/Ctrl+Shift+R available as soon as the run is queued,
3982
+ // not only after the server responds with the run id.
3983
+ state.lastRun = { job, instructions, employeeId };
3984
+ persistConversations();
3985
+ renderRail();
3986
+ renderActive();
3984
3987
 
3985
3988
  try {
3986
3989
  const run = await requestJson('/api/ai-hub/runs', {
@@ -4008,9 +4011,8 @@ async function startRun(job, instructions, employeeId, preassignedConvId) {
4008
4011
  renderRail();
4009
4012
  renderActive();
4010
4013
  startPolling();
4011
- // Issue #539: record last run for Cmd+Shift+R re-run and update in-memory
4012
- // preferences so the next palette open shows the correct recent section.
4013
- state.lastRun = { job, instructions, employeeId };
4014
+ // Issue #539: update in-memory preferences so the next palette open shows
4015
+ // the correct recent section.
4014
4016
  if (state.bootstrap && state.bootstrap.preferences) {
4015
4017
  const prefs = state.bootstrap.preferences;
4016
4018
  const nextIds = [job.id, ...(prefs.recentJobIds || []).filter((id) => id !== job.id)].slice(0, 8);