@a-company/paradigm 5.8.1 → 5.9.0

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/mcp.js CHANGED
@@ -4,6 +4,32 @@ import {
4
4
  loadDecisions,
5
5
  recordDecision
6
6
  } from "./chunk-EZ3GOCYC.js";
7
+ import {
8
+ acknowledgeMessages,
9
+ approveFileRequest,
10
+ buildMessage,
11
+ cleanStaleAgents,
12
+ createFileRequest,
13
+ createThread,
14
+ denyFileRequest,
15
+ expireOldRequests,
16
+ garbageCollect,
17
+ getMyIdentity,
18
+ getThreadMessages,
19
+ isAgentAsleep,
20
+ isPathDenied,
21
+ listAgents,
22
+ listFileRequests,
23
+ listThreads,
24
+ loadThread,
25
+ loadTrustConfig,
26
+ markAgentPollTime,
27
+ peekInbox,
28
+ readInbox,
29
+ recordAckSize,
30
+ registerAgent,
31
+ routeMessage
32
+ } from "./chunk-NQKQG45G.js";
7
33
  import {
8
34
  addStep,
9
35
  addToolBreadcrumb,
@@ -79,7 +105,7 @@ import {
79
105
  validateProtocol,
80
106
  validatePurposeFile,
81
107
  validateUniversityContent
82
- } from "./chunk-T3YGSZCI.js";
108
+ } from "./chunk-3UCH56D5.js";
83
109
  import "./chunk-L27I3CPZ.js";
84
110
  import {
85
111
  getWorkLogSummary,
@@ -133,16 +159,18 @@ import {
133
159
  queryEvents,
134
160
  resolveDebate,
135
161
  searchNotebooks
136
- } from "./chunk-B2RC3HEB.js";
162
+ } from "./chunk-V7BZBBI6.js";
137
163
  import {
138
164
  buildProfileEnrichment,
139
165
  init_agent_loader,
166
+ listAllGlobalAgentIds,
140
167
  loadAgentProfile,
141
168
  loadAllAgentProfiles,
169
+ loadProjectRoster,
142
170
  queryExpertise,
143
- saveAgentProfile,
171
+ saveProjectRoster,
144
172
  verifyIntegrity
145
- } from "./chunk-ITPJJIHG.js";
173
+ } from "./chunk-MA7G4CTI.js";
146
174
  import {
147
175
  getJournalStats,
148
176
  init_journal_loader,
@@ -2935,7 +2963,7 @@ function registerResources(server, getContext2) {
2935
2963
 
2936
2964
  // ../paradigm-mcp/src/tools/index.ts
2937
2965
  import * as os6 from "os";
2938
- import * as path34 from "path";
2966
+ import * as path33 from "path";
2939
2967
  import {
2940
2968
  ListToolsRequestSchema,
2941
2969
  CallToolRequestSchema
@@ -3741,7 +3769,7 @@ function navigateExplore(config, target, rootDir) {
3741
3769
  }
3742
3770
  if (result.paths.length === 0) {
3743
3771
  const areaSymbols = Object.entries(config.symbols).filter(
3744
- ([sym, path35]) => sym.toLowerCase().includes(targetLower) || path35.toLowerCase().includes(targetLower)
3772
+ ([sym, path34]) => sym.toLowerCase().includes(targetLower) || path34.toLowerCase().includes(targetLower)
3745
3773
  ).slice(0, 10);
3746
3774
  result.paths = [...new Set(areaSymbols.map(([, p]) => p))];
3747
3775
  result.symbols = areaSymbols.map(([s]) => s);
@@ -5684,8 +5712,10 @@ payloads:
5684
5712
 
5685
5713
  // ../paradigm-mcp/src/tools/orchestration.ts
5686
5714
  import * as fs12 from "fs";
5715
+ import * as os from "os";
5687
5716
  import * as path13 from "path";
5688
5717
  import * as yaml8 from "js-yaml";
5718
+ init_agent_loader();
5689
5719
  var SYMBOL_PATTERN = /[@#$%^!?&~][a-zA-Z0-9_-]+/g;
5690
5720
  var DEFAULT_MODELS = {
5691
5721
  architect: "opus",
@@ -5990,6 +6020,14 @@ async function handleOrchestrateInline(args, ctx) {
5990
6020
  trackToolCall(text2.length, "paradigm_orchestrate_inline");
5991
6021
  return { handled: true, text: text2 };
5992
6022
  }
6023
+ const roster = loadProjectRoster(ctx.rootDir);
6024
+ if (roster && manifest.agents) {
6025
+ const filtered = {};
6026
+ for (const [id, def] of Object.entries(manifest.agents)) {
6027
+ if (roster.includes(id)) filtered[id] = def;
6028
+ }
6029
+ manifest.agents = filtered;
6030
+ }
5993
6031
  const symbols = extractSymbols(task);
5994
6032
  const classification = classifyTaskLocal(task);
5995
6033
  const plan = planAgentSequence(task, manifest.agents, agentOverride, classification);
@@ -6021,10 +6059,10 @@ async function handleOrchestrateInline(args, ctx) {
6021
6059
  }
6022
6060
  let agentProfiles = /* @__PURE__ */ new Map();
6023
6061
  try {
6024
- const { loadAgentProfile: loadAgentProfile2, buildProfileEnrichment: buildProfileEnrichment2 } = await import("./agent-loader-DBF4OARL.js");
6062
+ const { loadAgentProfile: loadAgentProfile2, buildProfileEnrichment: buildProfileEnrichment2 } = await import("./agent-loader-X7TDYLFL.js");
6025
6063
  const { loadDecisions: loadDecisions3 } = await import("./decision-loader-WWCLIQPJ.js");
6026
6064
  const { loadJournalEntries: loadJournalEntries2 } = await import("./journal-loader-5EYSBFFY.js");
6027
- const { loadNominations: loadNominations2 } = await import("./nomination-engine-LPLCCDW2.js");
6065
+ const { loadNominations: loadNominations2 } = await import("./nomination-engine-LLREC5BZ.js");
6028
6066
  const recentDecisions = loadDecisions3(ctx.rootDir, { status: "active", limit: 5 }).map((d) => ({ title: d.title, decision: d.decision.slice(0, 150) }));
6029
6067
  const pendingNominations = loadNominations2(ctx.rootDir, { pending_only: true, limit: 10 }).map((n) => ({ urgency: n.urgency, brief: n.brief }));
6030
6068
  for (const stage of plan.stages) {
@@ -6120,6 +6158,51 @@ async function handleOrchestrateInline(args, ctx) {
6120
6158
  }
6121
6159
  } catch {
6122
6160
  }
6161
+ const orchestrationThread = `thr-orch-${orchestrationId}`;
6162
+ try {
6163
+ const symphony = await import("./symphony-loader-UZGON56V.js");
6164
+ const projectName = path13.basename(ctx.rootDir);
6165
+ const maestroId = `${projectName}/maestro`;
6166
+ try {
6167
+ const identity = symphony.getMyIdentity(ctx.rootDir);
6168
+ if (!identity) {
6169
+ symphony.registerAgent(ctx.rootDir, "maestro", "Maestro (orchestrator)");
6170
+ }
6171
+ } catch {
6172
+ }
6173
+ symphony.createThread(`Orchestration: ${task.slice(0, 80)}`, {
6174
+ id: maestroId,
6175
+ name: "Maestro",
6176
+ type: "agent",
6177
+ project: projectName,
6178
+ role: "orchestrator"
6179
+ });
6180
+ const threadsDir = path13.join(os.homedir(), ".paradigm", "score", "threads");
6181
+ const existingThreads = fs12.readdirSync(threadsDir).filter((f) => f.endsWith(".json")).sort();
6182
+ const latestThread = existingThreads[existingThreads.length - 1];
6183
+ if (latestThread) {
6184
+ const oldPath = path13.join(threadsDir, latestThread);
6185
+ const newPath = path13.join(threadsDir, `${orchestrationThread}.json`);
6186
+ const threadData = JSON.parse(fs12.readFileSync(oldPath, "utf8"));
6187
+ threadData.id = orchestrationThread;
6188
+ fs12.writeFileSync(newPath, JSON.stringify(threadData, null, 2), "utf8");
6189
+ if (oldPath !== newPath) fs12.unlinkSync(oldPath);
6190
+ }
6191
+ for (const stage of stagePrompts) {
6192
+ for (const agent of stage.agents) {
6193
+ const note = symphony.buildMessage({
6194
+ threadRoot: orchestrationThread,
6195
+ sender: { id: maestroId, name: "Maestro", type: "agent", project: projectName, role: "orchestrator" },
6196
+ intent: "task",
6197
+ text: `[Maestro] Stage ${stage.stage}: Assigned to ${agent.attribution || agent.agent} \u2014 ${agent.taskDescription || task}`,
6198
+ symbols,
6199
+ metadata: { task: { stage: stage.stage, canRunParallel: stage.canRunParallel } }
6200
+ });
6201
+ symphony.routeMessage(note);
6202
+ }
6203
+ }
6204
+ } catch {
6205
+ }
6123
6206
  const result = {
6124
6207
  orchestrationId,
6125
6208
  task,
@@ -6136,6 +6219,12 @@ async function handleOrchestrateInline(args, ctx) {
6136
6219
  "Do NOT synthesize agent responses \u2014 show them as distinct contributions from each agent",
6137
6220
  "After all agents in a stage complete, reconcile their outputs before proceeding to the next stage"
6138
6221
  ],
6222
+ // Symphony thread for live visibility in Conductor
6223
+ symphony: {
6224
+ orchestrationThread,
6225
+ instruction: "After each agent completes, call paradigm_symphony_send to report progress. This makes the work visible in Conductor.",
6226
+ perAgentInstruction: `When each agent finishes, run: paradigm_symphony_send threadId="${orchestrationThread}" intent="task-complete" text="[agentName] Summary of completed work" symbols=[touched symbols]`
6227
+ },
6139
6228
  // Claude Code: Use Task tool for parallel agent spawning
6140
6229
  claudeCode: {
6141
6230
  method: "Task tool",
@@ -6190,6 +6279,16 @@ async function handleAgentPrompt(args, ctx) {
6190
6279
  const handoffContext = args.handoffContext;
6191
6280
  const previousAgent = args.previousAgent;
6192
6281
  const manifest = loadAgentsManifest(ctx.rootDir);
6282
+ const rosterForPrompt = loadProjectRoster(ctx.rootDir);
6283
+ if (rosterForPrompt && !rosterForPrompt.includes(agentName)) {
6284
+ const text2 = JSON.stringify({
6285
+ warning: `Agent "${agentName}" is not on this project's roster`,
6286
+ suggestion: `Run paradigm_agent_activate id="${agentName}" to add it, or check .paradigm/roster.yaml`,
6287
+ activeRoster: rosterForPrompt
6288
+ }, null, 2);
6289
+ trackToolCall(text2.length, "paradigm_agent_prompt");
6290
+ return { handled: true, text: text2 };
6291
+ }
6193
6292
  const manifestAgent = manifest?.agents[agentName];
6194
6293
  const agentDef = {
6195
6294
  name: manifestAgent?.name || agentName,
@@ -6205,10 +6304,10 @@ async function handleAgentPrompt(args, ctx) {
6205
6304
  let profileEnrichment;
6206
6305
  let nickname;
6207
6306
  try {
6208
- const { loadAgentProfile: loadAgentProfile2, buildProfileEnrichment: buildProfileEnrichment2 } = await import("./agent-loader-DBF4OARL.js");
6307
+ const { loadAgentProfile: loadAgentProfile2, buildProfileEnrichment: buildProfileEnrichment2 } = await import("./agent-loader-X7TDYLFL.js");
6209
6308
  const { loadDecisions: loadDecisions3 } = await import("./decision-loader-WWCLIQPJ.js");
6210
6309
  const { loadJournalEntries: loadJournalEntries2 } = await import("./journal-loader-5EYSBFFY.js");
6211
- const { loadNominations: loadNominations2 } = await import("./nomination-engine-LPLCCDW2.js");
6310
+ const { loadNominations: loadNominations2 } = await import("./nomination-engine-LLREC5BZ.js");
6212
6311
  const profile = loadAgentProfile2(ctx.rootDir, agentName);
6213
6312
  if (profile) {
6214
6313
  nickname = profile.nickname;
@@ -9604,7 +9703,7 @@ function runPostflightCheck(filesModified, symbolsTouched, ctx) {
9604
9703
  // ../paradigm-mcp/src/tools/lore.ts
9605
9704
  init_lore_loader();
9606
9705
  import { execSync as execSync2 } from "child_process";
9607
- import * as os from "os";
9706
+ import * as os2 from "os";
9608
9707
  function resolveAuthorForMcp() {
9609
9708
  const envAuthor = process.env.PARADIGM_AUTHOR;
9610
9709
  if (envAuthor) return sanitize(envAuthor);
@@ -9614,7 +9713,7 @@ function resolveAuthorForMcp() {
9614
9713
  } catch {
9615
9714
  }
9616
9715
  try {
9617
- const username = os.userInfo().username;
9716
+ const username = os2.userInfo().username;
9618
9717
  if (username) return sanitize(username);
9619
9718
  } catch {
9620
9719
  }
@@ -10132,7 +10231,7 @@ async function handleLoreTool(name, args, ctx) {
10132
10231
  try {
10133
10232
  const agentId = process.env.PARADIGM_AGENT_ID;
10134
10233
  if (agentId && symbols_touched && symbols_touched.length > 0) {
10135
- const { updateExpertiseFromLore } = await import("./agent-loader-DBF4OARL.js");
10234
+ const { updateExpertiseFromLore } = await import("./agent-loader-X7TDYLFL.js");
10136
10235
  updateExpertiseFromLore(ctx.rootDir, agentId, {
10137
10236
  symbols_touched,
10138
10237
  confidence: confidence != null && confidence >= 0 && confidence <= 1 ? confidence : void 0
@@ -10303,7 +10402,7 @@ async function handleLoreTool(name, args, ctx) {
10303
10402
  try {
10304
10403
  const agentId = process.env.PARADIGM_AGENT_ID;
10305
10404
  if (agentId && success && entryToAssess.symbols_touched?.length) {
10306
- const { updateExpertiseFromAssessment } = await import("./agent-loader-DBF4OARL.js");
10405
+ const { updateExpertiseFromAssessment } = await import("./agent-loader-X7TDYLFL.js");
10307
10406
  updateExpertiseFromAssessment(ctx.rootDir, agentId, {
10308
10407
  symbols_touched: entryToAssess.symbols_touched,
10309
10408
  verdict
@@ -12766,7 +12865,7 @@ async function rebuildAssessmentIndex(rootDir) {
12766
12865
 
12767
12866
  // ../paradigm-mcp/src/tools/assessment.ts
12768
12867
  import { execSync as execSync4 } from "child_process";
12769
- import * as os2 from "os";
12868
+ import * as os3 from "os";
12770
12869
  function resolveAuthor() {
12771
12870
  const envAuthor = process.env.PARADIGM_AUTHOR;
12772
12871
  if (envAuthor) return sanitize2(envAuthor);
@@ -12776,7 +12875,7 @@ function resolveAuthor() {
12776
12875
  } catch {
12777
12876
  }
12778
12877
  try {
12779
- const username = os2.userInfo().username;
12878
+ const username = os3.userInfo().username;
12780
12879
  if (username) return sanitize2(username);
12781
12880
  } catch {
12782
12881
  }
@@ -13097,8 +13196,8 @@ function generateRunId() {
13097
13196
  var TEMPLATE_REGEX = /\{\{([^}]+)\}\}/g;
13098
13197
  function interpolate(value, scope) {
13099
13198
  if (typeof value === "string") {
13100
- return value.replace(TEMPLATE_REGEX, (_match, path35) => {
13101
- const resolved = resolvePath(path35.trim(), scope);
13199
+ return value.replace(TEMPLATE_REGEX, (_match, path34) => {
13200
+ const resolved = resolvePath(path34.trim(), scope);
13102
13201
  return resolved !== void 0 ? String(resolved) : _match;
13103
13202
  });
13104
13203
  }
@@ -13131,8 +13230,8 @@ function resolvePath(dotPath, scope) {
13131
13230
  return void 0;
13132
13231
  }
13133
13232
  }
13134
- function deepGet(obj, path35) {
13135
- const parts = path35.split(/[.\[\]]+/).filter(Boolean);
13233
+ function deepGet(obj, path34) {
13234
+ const parts = path34.split(/[.\[\]]+/).filter(Boolean);
13136
13235
  let current = obj;
13137
13236
  for (const part of parts) {
13138
13237
  if (current == null || typeof current !== "object") return void 0;
@@ -13368,11 +13467,11 @@ async function runPersonaObject(rootDir, persona, options) {
13368
13467
  }
13369
13468
  async function runChain(rootDir, chainId, options) {
13370
13469
  const start = Date.now();
13371
- const fs31 = await import("fs");
13372
- const path35 = await import("path");
13470
+ const fs30 = await import("fs");
13471
+ const path34 = await import("path");
13373
13472
  const yaml18 = await import("js-yaml");
13374
- const chainPath = path35.join(rootDir, ".paradigm", "personas", "chains", `${chainId}.yaml`);
13375
- if (!fs31.existsSync(chainPath)) {
13473
+ const chainPath = path34.join(rootDir, ".paradigm", "personas", "chains", `${chainId}.yaml`);
13474
+ if (!fs30.existsSync(chainPath)) {
13376
13475
  return {
13377
13476
  chain_id: chainId,
13378
13477
  status: "error",
@@ -13381,7 +13480,7 @@ async function runChain(rootDir, chainId, options) {
13381
13480
  duration_ms: Date.now() - start
13382
13481
  };
13383
13482
  }
13384
- const chain = yaml18.load(fs31.readFileSync(chainPath, "utf8"));
13483
+ const chain = yaml18.load(fs30.readFileSync(chainPath, "utf8"));
13385
13484
  let permutation;
13386
13485
  if (options.permutation && chain.permutations) {
13387
13486
  permutation = chain.permutations.find((p) => p.id === options.permutation);
@@ -13485,8 +13584,8 @@ function validateInterpolation(persona) {
13485
13584
  const serialized = JSON.stringify(step);
13486
13585
  const templates = serialized.match(TEMPLATE_REGEX) || [];
13487
13586
  for (const template of templates) {
13488
- const path35 = template.replace("{{", "").replace("}}", "").trim();
13489
- const [namespace, ...rest] = path35.split(".");
13587
+ const path34 = template.replace("{{", "").replace("}}", "").trim();
13588
+ const [namespace, ...rest] = path34.split(".");
13490
13589
  const key = rest.join(".");
13491
13590
  switch (namespace) {
13492
13591
  case "fixtures":
@@ -15557,9 +15656,9 @@ import { execSync as execSync6 } from "child_process";
15557
15656
  // ../paradigm-mcp/src/utils/conductor-loader.ts
15558
15657
  import * as fs26 from "fs";
15559
15658
  import * as path28 from "path";
15560
- import * as os3 from "os";
15659
+ import * as os4 from "os";
15561
15660
  import { execSync as execSync5 } from "child_process";
15562
- var CONDUCTOR_DIR = path28.join(os3.homedir(), ".conductor");
15661
+ var CONDUCTOR_DIR = path28.join(os4.homedir(), ".conductor");
15563
15662
  var SESSIONS_DIR = path28.join(CONDUCTOR_DIR, "sessions");
15564
15663
  function ensureSessionsDir() {
15565
15664
  if (!fs26.existsSync(SESSIONS_DIR)) {
@@ -15840,583 +15939,6 @@ This session is no longer visible in the Conductor overlay.`,
15840
15939
  }
15841
15940
  }
15842
15941
 
15843
- // ../paradigm-mcp/src/utils/symphony-loader.ts
15844
- import * as fs27 from "fs";
15845
- import * as path29 from "path";
15846
- import * as os4 from "os";
15847
- import * as crypto from "crypto";
15848
- var SCORE_DIR = path29.join(os4.homedir(), ".paradigm", "score");
15849
- var LEGACY_MAIL_DIR = path29.join(os4.homedir(), ".paradigm", "mail");
15850
- var AGENTS_DIR = path29.join(SCORE_DIR, "agents");
15851
- var THREADS_DIR = path29.join(SCORE_DIR, "threads");
15852
- var FILE_REQUESTS_DIR = path29.join(SCORE_DIR, "file-requests");
15853
- var TRUST_CONFIG_PATH = path29.join(SCORE_DIR, "trust.yaml");
15854
- var FILE_REQUEST_TTL_MS = 60 * 60 * 1e3;
15855
- var DEFAULT_TRUST = {
15856
- users: {},
15857
- defaults: {
15858
- level: "restricted",
15859
- autoApprove: [],
15860
- neverApprove: [
15861
- ".env*",
15862
- "**/*.key",
15863
- "**/*.pem",
15864
- "**/credentials*",
15865
- "**/secrets/**"
15866
- ]
15867
- }
15868
- };
15869
- function migrateFromLegacyMail() {
15870
- if (fs27.existsSync(LEGACY_MAIL_DIR) && !fs27.existsSync(SCORE_DIR)) {
15871
- try {
15872
- fs27.renameSync(LEGACY_MAIL_DIR, SCORE_DIR);
15873
- } catch {
15874
- }
15875
- }
15876
- }
15877
- function ensureScoreDirs() {
15878
- migrateFromLegacyMail();
15879
- for (const dir of [AGENTS_DIR, THREADS_DIR, FILE_REQUESTS_DIR]) {
15880
- if (!fs27.existsSync(dir)) {
15881
- fs27.mkdirSync(dir, { recursive: true });
15882
- }
15883
- }
15884
- }
15885
- function getAgentDir(agentId) {
15886
- return path29.join(AGENTS_DIR, agentId);
15887
- }
15888
- function ensureAgentDir(agentId) {
15889
- const dir = getAgentDir(agentId);
15890
- if (!fs27.existsSync(dir)) {
15891
- fs27.mkdirSync(dir, { recursive: true });
15892
- }
15893
- return dir;
15894
- }
15895
- function readJsonlFile(filePath) {
15896
- if (!fs27.existsSync(filePath)) return [];
15897
- const content = fs27.readFileSync(filePath, "utf-8");
15898
- const lines = content.split("\n").filter((line) => line.trim().length > 0);
15899
- const items = [];
15900
- for (const line of lines) {
15901
- try {
15902
- items.push(JSON.parse(line));
15903
- } catch {
15904
- }
15905
- }
15906
- return items;
15907
- }
15908
- function appendJsonlLine(filePath, item) {
15909
- const dir = path29.dirname(filePath);
15910
- if (!fs27.existsSync(dir)) {
15911
- fs27.mkdirSync(dir, { recursive: true });
15912
- }
15913
- fs27.appendFileSync(filePath, JSON.stringify(item) + "\n", "utf-8");
15914
- }
15915
- function sanitizeId(name) {
15916
- return name.toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "").slice(0, 40) || "unknown";
15917
- }
15918
- function resolveProjectName(projectDir2) {
15919
- try {
15920
- const configPath = path29.join(projectDir2, ".paradigm", "config.yaml");
15921
- if (fs27.existsSync(configPath)) {
15922
- const content = fs27.readFileSync(configPath, "utf-8");
15923
- const match = content.match(/^project:\s*(.+)$/m);
15924
- if (match) return sanitizeId(match[1].trim().replace(/["']/g, ""));
15925
- }
15926
- } catch {
15927
- }
15928
- return sanitizeId(path29.basename(projectDir2));
15929
- }
15930
- function resolveAgentIdentity(projectDir2, role) {
15931
- const project = resolveProjectName(projectDir2);
15932
- const agentRole = role || "core";
15933
- return `${project}/${agentRole}`;
15934
- }
15935
- function registerAgent(projectDir2, role, label) {
15936
- ensureScoreDirs();
15937
- const agentId = resolveAgentIdentity(projectDir2, role);
15938
- const agentDir = ensureAgentDir(agentId);
15939
- const project = resolveProjectName(projectDir2);
15940
- const identity = {
15941
- id: agentId,
15942
- name: label || `${project} (${role || "core"})`,
15943
- type: "agent",
15944
- project,
15945
- role: role || "core",
15946
- pid: process.pid,
15947
- startedAt: (/* @__PURE__ */ new Date()).toISOString(),
15948
- label
15949
- };
15950
- fs27.writeFileSync(
15951
- path29.join(agentDir, "identity.json"),
15952
- JSON.stringify(identity, null, 2),
15953
- "utf-8"
15954
- );
15955
- return identity;
15956
- }
15957
- function unregisterAgent(agentId) {
15958
- const agentDir = getAgentDir(agentId);
15959
- if (!fs27.existsSync(agentDir)) return false;
15960
- try {
15961
- fs27.rmSync(agentDir, { recursive: true, force: true });
15962
- return true;
15963
- } catch {
15964
- return false;
15965
- }
15966
- }
15967
- function listAgents() {
15968
- ensureScoreDirs();
15969
- if (!fs27.existsSync(AGENTS_DIR)) return [];
15970
- const agents = [];
15971
- const projectDirs = fs27.readdirSync(AGENTS_DIR, { withFileTypes: true }).filter((d) => d.isDirectory());
15972
- for (const projectDir2 of projectDirs) {
15973
- const projectPath = path29.join(AGENTS_DIR, projectDir2.name);
15974
- const roleDirs = fs27.readdirSync(projectPath, { withFileTypes: true }).filter((d) => d.isDirectory());
15975
- for (const roleDir of roleDirs) {
15976
- const identityPath = path29.join(projectPath, roleDir.name, "identity.json");
15977
- if (!fs27.existsSync(identityPath)) continue;
15978
- try {
15979
- const content = fs27.readFileSync(identityPath, "utf-8");
15980
- const identity = JSON.parse(content);
15981
- agents.push(identity);
15982
- } catch {
15983
- }
15984
- }
15985
- }
15986
- return agents;
15987
- }
15988
- function cleanStaleAgents() {
15989
- const agents = listAgents();
15990
- let cleaned = 0;
15991
- for (const agent of agents) {
15992
- if (!isProcessAlive2(agent.pid)) {
15993
- unregisterAgent(agent.id);
15994
- cleaned++;
15995
- }
15996
- }
15997
- return cleaned;
15998
- }
15999
- function getMyIdentity(projectDir2) {
16000
- const agentId = resolveAgentIdentity(projectDir2);
16001
- const identityPath = path29.join(getAgentDir(agentId), "identity.json");
16002
- if (!fs27.existsSync(identityPath)) return null;
16003
- try {
16004
- return JSON.parse(fs27.readFileSync(identityPath, "utf-8"));
16005
- } catch {
16006
- return null;
16007
- }
16008
- }
16009
- function markAgentPollTime(agentId, statusBlurb) {
16010
- const identityPath = path29.join(getAgentDir(agentId), "identity.json");
16011
- if (!fs27.existsSync(identityPath)) return;
16012
- try {
16013
- const identity = JSON.parse(fs27.readFileSync(identityPath, "utf-8"));
16014
- identity.lastPoll = (/* @__PURE__ */ new Date()).toISOString();
16015
- if (statusBlurb !== void 0) {
16016
- identity.statusBlurb = statusBlurb || void 0;
16017
- }
16018
- fs27.writeFileSync(identityPath, JSON.stringify(identity, null, 2), "utf-8");
16019
- } catch {
16020
- }
16021
- }
16022
- function isAgentAsleep(identity, thresholdMs = 6e4) {
16023
- if (!identity.lastPoll) return true;
16024
- const lastPoll = new Date(identity.lastPoll).getTime();
16025
- return Date.now() - lastPoll > thresholdMs;
16026
- }
16027
- function inboxPath(agentId) {
16028
- return path29.join(getAgentDir(agentId), "inbox.jsonl");
16029
- }
16030
- function outboxPath(agentId) {
16031
- return path29.join(getAgentDir(agentId), "outbox.jsonl");
16032
- }
16033
- function ackPath(agentId) {
16034
- return path29.join(getAgentDir(agentId), "ack.json");
16035
- }
16036
- function peekInbox(agentId) {
16037
- const filePath = inboxPath(agentId);
16038
- if (!fs27.existsSync(filePath)) return { hasNew: false, inboxSize: 0 };
16039
- const stat = fs27.statSync(filePath);
16040
- const inboxSize = stat.size;
16041
- const ack = readAck(agentId);
16042
- if (!ack) {
16043
- return { hasNew: inboxSize > 0, inboxSize };
16044
- }
16045
- const ackSizePath = path29.join(getAgentDir(agentId), "ack-size.json");
16046
- if (fs27.existsSync(ackSizePath)) {
16047
- try {
16048
- const ackSize = JSON.parse(fs27.readFileSync(ackSizePath, "utf-8"));
16049
- return { hasNew: inboxSize > (ackSize.size || 0), inboxSize };
16050
- } catch {
16051
- }
16052
- }
16053
- return { hasNew: inboxSize > 0, inboxSize };
16054
- }
16055
- function recordAckSize(agentId) {
16056
- const filePath = inboxPath(agentId);
16057
- const ackSizePath = path29.join(getAgentDir(agentId), "ack-size.json");
16058
- try {
16059
- const size = fs27.existsSync(filePath) ? fs27.statSync(filePath).size : 0;
16060
- ensureAgentDir(agentId);
16061
- fs27.writeFileSync(ackSizePath, JSON.stringify({ size }), "utf-8");
16062
- } catch {
16063
- }
16064
- }
16065
- function appendToInbox(agentId, message) {
16066
- ensureAgentDir(agentId);
16067
- appendJsonlLine(inboxPath(agentId), message);
16068
- }
16069
- function readInbox(agentId, afterAck) {
16070
- const messages = readJsonlFile(inboxPath(agentId));
16071
- if (!afterAck) {
16072
- const ack = readAck(agentId);
16073
- if (ack) {
16074
- const ackIndex2 = messages.findIndex((m) => m.id === ack);
16075
- if (ackIndex2 >= 0) return messages.slice(ackIndex2 + 1);
16076
- }
16077
- return messages;
16078
- }
16079
- const ackIndex = messages.findIndex((m) => m.id === afterAck);
16080
- if (ackIndex >= 0) return messages.slice(ackIndex + 1);
16081
- return messages;
16082
- }
16083
- function appendToOutbox(agentId, message) {
16084
- ensureAgentDir(agentId);
16085
- appendJsonlLine(outboxPath(agentId), message);
16086
- }
16087
- function acknowledgeMessages(agentId, lastMessageId) {
16088
- const filePath = ackPath(agentId);
16089
- ensureAgentDir(agentId);
16090
- fs27.writeFileSync(filePath, JSON.stringify({ lastAck: lastMessageId }), "utf-8");
16091
- }
16092
- function readAck(agentId) {
16093
- const filePath = ackPath(agentId);
16094
- if (!fs27.existsSync(filePath)) return null;
16095
- try {
16096
- const content = JSON.parse(fs27.readFileSync(filePath, "utf-8"));
16097
- return content.lastAck || null;
16098
- } catch {
16099
- return null;
16100
- }
16101
- }
16102
- function garbageCollect(agentId) {
16103
- const ack = readAck(agentId);
16104
- if (!ack) return 0;
16105
- const filePath = inboxPath(agentId);
16106
- const messages = readJsonlFile(filePath);
16107
- const ackIndex = messages.findIndex((m) => m.id === ack);
16108
- if (ackIndex < 0) return 0;
16109
- const kept = messages.slice(ackIndex + 1);
16110
- const removed = messages.length - kept.length;
16111
- if (kept.length === 0) {
16112
- if (fs27.existsSync(filePath)) fs27.writeFileSync(filePath, "", "utf-8");
16113
- } else {
16114
- fs27.writeFileSync(filePath, kept.map((m) => JSON.stringify(m)).join("\n") + "\n", "utf-8");
16115
- }
16116
- return removed;
16117
- }
16118
- function threadPath(threadId) {
16119
- return path29.join(THREADS_DIR, `${threadId}.json`);
16120
- }
16121
- function createThread(topic, initiator) {
16122
- ensureScoreDirs();
16123
- const id = "thr-" + crypto.randomBytes(4).toString("hex");
16124
- const now = (/* @__PURE__ */ new Date()).toISOString();
16125
- const thread = {
16126
- id,
16127
- topic,
16128
- initiator,
16129
- participants: [initiator],
16130
- status: "active",
16131
- createdAt: now,
16132
- lastActivity: now,
16133
- messageCount: 0
16134
- };
16135
- fs27.writeFileSync(threadPath(id), JSON.stringify(thread, null, 2), "utf-8");
16136
- return thread;
16137
- }
16138
- function loadThread(threadId) {
16139
- const filePath = threadPath(threadId);
16140
- if (!fs27.existsSync(filePath)) return null;
16141
- try {
16142
- return JSON.parse(fs27.readFileSync(filePath, "utf-8"));
16143
- } catch {
16144
- return null;
16145
- }
16146
- }
16147
- function listThreads(status) {
16148
- ensureScoreDirs();
16149
- if (!fs27.existsSync(THREADS_DIR)) return [];
16150
- const files = fs27.readdirSync(THREADS_DIR).filter((f) => f.endsWith(".json"));
16151
- const threads = [];
16152
- for (const file of files) {
16153
- try {
16154
- const content = fs27.readFileSync(path29.join(THREADS_DIR, file), "utf-8");
16155
- const thread = JSON.parse(content);
16156
- if (!status || thread.status === status) {
16157
- threads.push(thread);
16158
- }
16159
- } catch {
16160
- }
16161
- }
16162
- return threads.sort((a, b) => b.lastActivity.localeCompare(a.lastActivity));
16163
- }
16164
- function updateThread(threadId, partial) {
16165
- const thread = loadThread(threadId);
16166
- if (!thread) return false;
16167
- const updated = { ...thread, ...partial };
16168
- fs27.writeFileSync(threadPath(threadId), JSON.stringify(updated, null, 2), "utf-8");
16169
- return true;
16170
- }
16171
- function getThreadMessages(threadId) {
16172
- const agents = listAgents();
16173
- const messages = [];
16174
- for (const agent of agents) {
16175
- const inbox = readJsonlFile(inboxPath(agent.id));
16176
- const outbox = readJsonlFile(outboxPath(agent.id));
16177
- for (const msg of [...inbox, ...outbox]) {
16178
- if (msg.threadRoot === threadId || msg.id === threadId) {
16179
- if (!messages.some((m) => m.id === msg.id)) {
16180
- messages.push(msg);
16181
- }
16182
- }
16183
- }
16184
- }
16185
- return messages.sort((a, b) => a.timestamp.localeCompare(b.timestamp));
16186
- }
16187
- function buildMessage(params) {
16188
- return {
16189
- id: crypto.randomUUID(),
16190
- parentId: params.parentId,
16191
- threadRoot: params.threadRoot,
16192
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
16193
- sender: params.sender,
16194
- recipients: params.recipients,
16195
- intent: params.intent,
16196
- content: {
16197
- text: params.text,
16198
- diff: params.diff,
16199
- decision: params.decision
16200
- },
16201
- symbols: params.symbols || [],
16202
- attachments: params.attachments,
16203
- metadata: params.metadata
16204
- };
16205
- }
16206
- function routeMessage(message) {
16207
- ensureScoreDirs();
16208
- appendToOutbox(message.sender.id, message);
16209
- let deliveryCount = 0;
16210
- if (message.recipients && message.recipients.length > 0) {
16211
- for (const recipient of message.recipients) {
16212
- appendToInbox(recipient.id, message);
16213
- deliveryCount++;
16214
- }
16215
- } else {
16216
- const agents = listAgents();
16217
- for (const agent of agents) {
16218
- if (agent.id !== message.sender.id) {
16219
- appendToInbox(agent.id, message);
16220
- deliveryCount++;
16221
- }
16222
- }
16223
- }
16224
- if (message.threadRoot) {
16225
- const thread = loadThread(message.threadRoot);
16226
- if (thread) {
16227
- const isParticipant = thread.participants.some((p) => p.id === message.sender.id);
16228
- const updatedParticipants = isParticipant ? thread.participants : [...thread.participants, message.sender];
16229
- updateThread(message.threadRoot, {
16230
- participants: updatedParticipants,
16231
- lastActivity: message.timestamp,
16232
- messageCount: thread.messageCount + 1
16233
- });
16234
- }
16235
- }
16236
- return deliveryCount;
16237
- }
16238
- function fileRequestPath(requestId) {
16239
- return path29.join(FILE_REQUESTS_DIR, `${requestId}.json`);
16240
- }
16241
- function loadTrustConfig() {
16242
- if (!fs27.existsSync(TRUST_CONFIG_PATH)) return DEFAULT_TRUST;
16243
- try {
16244
- const content = fs27.readFileSync(TRUST_CONFIG_PATH, "utf-8");
16245
- try {
16246
- return JSON.parse(content);
16247
- } catch {
16248
- return DEFAULT_TRUST;
16249
- }
16250
- } catch {
16251
- return DEFAULT_TRUST;
16252
- }
16253
- }
16254
- function createFileRequest(params) {
16255
- ensureScoreDirs();
16256
- const requestId = "freq-" + crypto.randomBytes(4).toString("hex");
16257
- const record = {
16258
- request: {
16259
- requestId,
16260
- filePath: params.filePath,
16261
- reason: params.reason,
16262
- requester: params.requester,
16263
- urgency: params.urgency || "normal",
16264
- snippet: params.snippet,
16265
- threadRoot: params.threadRoot
16266
- },
16267
- status: "pending",
16268
- createdAt: (/* @__PURE__ */ new Date()).toISOString()
16269
- };
16270
- fs27.writeFileSync(fileRequestPath(requestId), JSON.stringify(record, null, 2), "utf-8");
16271
- return record;
16272
- }
16273
- function loadFileRequest(requestId) {
16274
- const filePath = fileRequestPath(requestId);
16275
- if (!fs27.existsSync(filePath)) return null;
16276
- try {
16277
- return JSON.parse(fs27.readFileSync(filePath, "utf-8"));
16278
- } catch {
16279
- return null;
16280
- }
16281
- }
16282
- function listFileRequests(status) {
16283
- ensureScoreDirs();
16284
- if (!fs27.existsSync(FILE_REQUESTS_DIR)) return [];
16285
- const files = fs27.readdirSync(FILE_REQUESTS_DIR).filter((f) => f.endsWith(".json"));
16286
- const requests = [];
16287
- for (const file of files) {
16288
- try {
16289
- const content = fs27.readFileSync(path29.join(FILE_REQUESTS_DIR, file), "utf-8");
16290
- const record = JSON.parse(content);
16291
- if (!status || record.status === status) {
16292
- requests.push(record);
16293
- }
16294
- } catch {
16295
- }
16296
- }
16297
- return requests.sort((a, b) => b.createdAt.localeCompare(a.createdAt));
16298
- }
16299
- function approveFileRequest(requestId, projectDir2, redact) {
16300
- const record = loadFileRequest(requestId);
16301
- if (!record) return { success: false, error: `File request not found: ${requestId}` };
16302
- if (record.status !== "pending") return { success: false, error: `Request already ${record.status}` };
16303
- const absolutePath = path29.resolve(projectDir2, record.request.filePath);
16304
- if (!absolutePath.startsWith(path29.resolve(projectDir2))) {
16305
- return { success: false, error: "File path escapes project directory" };
16306
- }
16307
- if (!fs27.existsSync(absolutePath)) {
16308
- return { success: false, error: `File not found: ${record.request.filePath}` };
16309
- }
16310
- try {
16311
- let content = fs27.readFileSync(absolutePath, "utf-8");
16312
- let encoding = "utf8";
16313
- if (redact) {
16314
- const secretPatterns = [
16315
- /(?:api[_-]?key|secret|token|password|credential|auth)\s*[:=]/i,
16316
- /(?:^|\s)(?:export\s+)?[A-Z_]+(?:KEY|SECRET|TOKEN|PASSWORD|CREDENTIAL)\s*=/,
16317
- /-----BEGIN (?:RSA |EC )?PRIVATE KEY-----/
16318
- ];
16319
- content = content.split("\n").map((line) => {
16320
- for (const pattern of secretPatterns) {
16321
- if (pattern.test(line)) return "[REDACTED]";
16322
- }
16323
- return line;
16324
- }).join("\n");
16325
- }
16326
- const hash = crypto.createHash("sha256").update(content).digest("hex");
16327
- const delivery = {
16328
- requestId,
16329
- filePath: record.request.filePath,
16330
- content,
16331
- encoding,
16332
- size: Buffer.byteLength(content),
16333
- hash
16334
- };
16335
- record.status = "approved";
16336
- record.resolvedAt = (/* @__PURE__ */ new Date()).toISOString();
16337
- record.delivery = delivery;
16338
- fs27.writeFileSync(fileRequestPath(requestId), JSON.stringify(record, null, 2), "utf-8");
16339
- const deliveryMessage = buildMessage({
16340
- sender: { id: "system", name: "File Transfer", type: "human" },
16341
- recipients: [record.request.requester],
16342
- intent: "fileDelivery",
16343
- text: `File delivered: ${record.request.filePath} (${delivery.size} bytes, SHA-256: ${hash.slice(0, 12)}...)`,
16344
- threadRoot: record.request.threadRoot,
16345
- symbols: []
16346
- });
16347
- deliveryMessage.attachments = [{
16348
- name: path29.basename(record.request.filePath),
16349
- type: "file",
16350
- content: delivery.content,
16351
- encoding: delivery.encoding
16352
- }];
16353
- routeMessage(deliveryMessage);
16354
- return { success: true, delivery };
16355
- } catch (err2) {
16356
- return { success: false, error: `Failed to read file: ${err2.message}` };
16357
- }
16358
- }
16359
- function denyFileRequest(requestId, reason) {
16360
- const record = loadFileRequest(requestId);
16361
- if (!record || record.status !== "pending") return false;
16362
- record.status = "denied";
16363
- record.resolvedAt = (/* @__PURE__ */ new Date()).toISOString();
16364
- record.denyReason = reason;
16365
- fs27.writeFileSync(fileRequestPath(requestId), JSON.stringify(record, null, 2), "utf-8");
16366
- const denialMessage = buildMessage({
16367
- sender: { id: "system", name: "File Transfer", type: "human" },
16368
- recipients: [record.request.requester],
16369
- intent: "fileDenied",
16370
- text: `File request denied: ${record.request.filePath}${reason ? ` \u2014 ${reason}` : ""}`,
16371
- threadRoot: record.request.threadRoot,
16372
- symbols: []
16373
- });
16374
- routeMessage(denialMessage);
16375
- return true;
16376
- }
16377
- function matchesGlob(filePath, pattern) {
16378
- let regex = pattern.replace(/\./g, "\\.").replace(/\*\*/g, "{{GLOBSTAR}}").replace(/\*/g, "[^/]*").replace(/\?/g, "[^/]").replace(/\{\{GLOBSTAR\}\}/g, ".*");
16379
- return new RegExp(`^${regex}$`).test(filePath);
16380
- }
16381
- function isPathDenied(filePath, config, user) {
16382
- const trust = config || loadTrustConfig();
16383
- if (user && trust.users[user]) {
16384
- for (const pattern of trust.users[user].neverApprove) {
16385
- if (matchesGlob(filePath, pattern)) return true;
16386
- }
16387
- }
16388
- for (const pattern of trust.defaults.neverApprove) {
16389
- if (matchesGlob(filePath, pattern)) return true;
16390
- }
16391
- return false;
16392
- }
16393
- function expireOldRequests() {
16394
- const requests = listFileRequests("pending");
16395
- let expired = 0;
16396
- for (const record of requests) {
16397
- const age = Date.now() - new Date(record.createdAt).getTime();
16398
- if (age > FILE_REQUEST_TTL_MS) {
16399
- record.status = "expired";
16400
- record.resolvedAt = (/* @__PURE__ */ new Date()).toISOString();
16401
- fs27.writeFileSync(
16402
- fileRequestPath(record.request.requestId),
16403
- JSON.stringify(record, null, 2),
16404
- "utf-8"
16405
- );
16406
- expired++;
16407
- }
16408
- }
16409
- return expired;
16410
- }
16411
- function isProcessAlive2(pid) {
16412
- try {
16413
- process.kill(pid, 0);
16414
- return true;
16415
- } catch {
16416
- return false;
16417
- }
16418
- }
16419
-
16420
15942
  // ../paradigm-mcp/src/tools/symphony.ts
16421
15943
  function getSymphonyToolsList() {
16422
15944
  return [
@@ -17720,14 +17242,14 @@ async function handleUniversityTool(name, args, ctx) {
17720
17242
  }
17721
17243
 
17722
17244
  // ../paradigm-mcp/src/utils/platform-bridge.ts
17723
- import * as fs28 from "fs";
17724
- import * as path30 from "path";
17245
+ import * as fs27 from "fs";
17246
+ import * as path29 from "path";
17725
17247
  import * as yaml16 from "js-yaml";
17726
17248
  function resolvePlatformPort(projectDir2) {
17727
17249
  try {
17728
- const configPath = path30.join(projectDir2, ".paradigm", "config.yaml");
17729
- if (fs28.existsSync(configPath)) {
17730
- const config = yaml16.load(fs28.readFileSync(configPath, "utf-8"));
17250
+ const configPath = path29.join(projectDir2, ".paradigm", "config.yaml");
17251
+ if (fs27.existsSync(configPath)) {
17252
+ const config = yaml16.load(fs27.readFileSync(configPath, "utf-8"));
17731
17253
  const platform2 = config.platform;
17732
17254
  if (platform2?.port && typeof platform2.port === "number") {
17733
17255
  return platform2.port;
@@ -17739,16 +17261,16 @@ function resolvePlatformPort(projectDir2) {
17739
17261
  }
17740
17262
  function resolveAgentId(projectDir2) {
17741
17263
  try {
17742
- const configPath = path30.join(projectDir2, ".paradigm", "config.yaml");
17743
- if (fs28.existsSync(configPath)) {
17744
- const config = yaml16.load(fs28.readFileSync(configPath, "utf-8"));
17745
- const project = config.project || path30.basename(projectDir2);
17264
+ const configPath = path29.join(projectDir2, ".paradigm", "config.yaml");
17265
+ if (fs27.existsSync(configPath)) {
17266
+ const config = yaml16.load(fs27.readFileSync(configPath, "utf-8"));
17267
+ const project = config.project || path29.basename(projectDir2);
17746
17268
  const role = config.role || "core";
17747
17269
  return `${project}/${role}`;
17748
17270
  }
17749
17271
  } catch {
17750
17272
  }
17751
- return `${path30.basename(projectDir2)}/core`;
17273
+ return `${path29.basename(projectDir2)}/core`;
17752
17274
  }
17753
17275
  async function sendAgentCommand(projectDir2, command, payload) {
17754
17276
  const port = resolvePlatformPort(projectDir2);
@@ -18123,6 +17645,7 @@ async function handleAgentTool(name, args, ctx) {
18123
17645
  switch (name) {
18124
17646
  case "paradigm_agent_list": {
18125
17647
  const profiles = loadAllAgentProfiles(ctx.rootDir);
17648
+ const roster = loadProjectRoster(ctx.rootDir);
18126
17649
  if (profiles.length === 0) {
18127
17650
  return {
18128
17651
  handled: true,
@@ -18133,15 +17656,18 @@ async function handleAgentTool(name, args, ctx) {
18133
17656
  }, null, 2)
18134
17657
  };
18135
17658
  }
17659
+ const activeProfiles = roster ? profiles.filter((p) => roster.includes(p.id)) : profiles;
17660
+ const inactiveCount = roster ? profiles.length - activeProfiles.length : 0;
18136
17661
  return {
18137
17662
  handled: true,
18138
17663
  text: JSON.stringify({
18139
- count: profiles.length,
18140
- agents: profiles.map((p) => ({
17664
+ count: activeProfiles.length,
17665
+ totalAvailable: profiles.length,
17666
+ ...roster ? { rosterActive: true, inactiveCount } : { rosterActive: false },
17667
+ agents: activeProfiles.map((p) => ({
18141
17668
  id: p.id,
18142
17669
  role: p.role,
18143
17670
  nickname: p.nickname,
18144
- benched: p.benched || false,
18145
17671
  personality: p.personality,
18146
17672
  topExpertise: (p.expertise || []).sort((a, b) => b.confidence - a.confidence).slice(0, 5).map((e) => ({
18147
17673
  symbol: e.symbol,
@@ -18239,15 +17765,20 @@ async function handleAgentTool(name, args, ctx) {
18239
17765
  text: JSON.stringify({ error: `Agent "${benchId}" not found` }, null, 2)
18240
17766
  };
18241
17767
  }
18242
- benchProfile.benched = true;
18243
- benchProfile.updated = (/* @__PURE__ */ new Date()).toISOString();
18244
- saveAgentProfile(benchId, benchProfile, "global");
17768
+ let currentRoster = loadProjectRoster(ctx.rootDir);
17769
+ if (currentRoster) {
17770
+ currentRoster = currentRoster.filter((id) => id !== benchId);
17771
+ } else {
17772
+ currentRoster = listAllGlobalAgentIds().filter((id) => id !== benchId);
17773
+ }
17774
+ saveProjectRoster(ctx.rootDir, currentRoster);
18245
17775
  return {
18246
17776
  handled: true,
18247
17777
  text: JSON.stringify({
18248
17778
  id: benchId,
18249
- benched: true,
18250
- note: `${benchId} is now benched. Maestro will skip this agent during orchestration.`
17779
+ removedFromRoster: true,
17780
+ rosterCount: currentRoster.length,
17781
+ note: `${benchId} removed from this project's roster. Still available globally.`
18251
17782
  }, null, 2)
18252
17783
  };
18253
17784
  }
@@ -18260,15 +17791,21 @@ async function handleAgentTool(name, args, ctx) {
18260
17791
  text: JSON.stringify({ error: `Agent "${activateId}" not found` }, null, 2)
18261
17792
  };
18262
17793
  }
18263
- activateProfile.benched = false;
18264
- activateProfile.updated = (/* @__PURE__ */ new Date()).toISOString();
18265
- saveAgentProfile(activateId, activateProfile, "global");
17794
+ let activateRoster = loadProjectRoster(ctx.rootDir);
17795
+ if (activateRoster) {
17796
+ if (!activateRoster.includes(activateId)) {
17797
+ activateRoster.push(activateId);
17798
+ saveProjectRoster(ctx.rootDir, activateRoster);
17799
+ }
17800
+ } else {
17801
+ }
18266
17802
  return {
18267
17803
  handled: true,
18268
17804
  text: JSON.stringify({
18269
17805
  id: activateId,
18270
- benched: false,
18271
- note: `${activateId} is now active. Maestro will include this agent in orchestration.`
17806
+ addedToRoster: true,
17807
+ rosterCount: activateRoster?.length ?? "all (no roster)",
17808
+ note: `${activateId} is active on this project's roster.`
18272
17809
  }, null, 2)
18273
17810
  };
18274
17811
  }
@@ -18445,7 +17982,7 @@ async function handleNotebookTool(name, args, ctx) {
18445
17982
  const concepts = args.concepts || [];
18446
17983
  const tags = args.tags || [];
18447
17984
  const confidence = args.confidence ?? 0.7;
18448
- const scope = args.scope || "global";
17985
+ const scope = args.scope || (ctx.rootDir ? "project" : "global");
18449
17986
  const result = addNotebookEntry(
18450
17987
  agentId,
18451
17988
  {
@@ -18474,7 +18011,7 @@ async function handleNotebookTool(name, args, ctx) {
18474
18011
  case "paradigm_notebook_promote": {
18475
18012
  const agentId = args.agentId;
18476
18013
  const loreEntryId = args.loreEntryId;
18477
- const scope = args.scope || "global";
18014
+ const scope = args.scope || (ctx.rootDir ? "project" : "global");
18478
18015
  const result = await promoteFromLore(agentId, loreEntryId, ctx.rootDir, scope);
18479
18016
  if (!result) {
18480
18017
  return {
@@ -18505,8 +18042,8 @@ async function handleNotebookTool(name, args, ctx) {
18505
18042
  }
18506
18043
 
18507
18044
  // ../paradigm-mcp/src/utils/docs-loader.ts
18508
- import * as fs29 from "fs";
18509
- import * as path31 from "path";
18045
+ import * as fs28 from "fs";
18046
+ import * as path30 from "path";
18510
18047
  import * as yaml17 from "js-yaml";
18511
18048
  var SCAN_INDEX_PATH = ".paradigm/scan-index.json";
18512
18049
  var FLOW_INDEX_PATH = ".paradigm/flow-index.json";
@@ -18524,12 +18061,12 @@ var DEFAULT_CONFIG = {
18524
18061
  output: ".paradigm/docs-site"
18525
18062
  };
18526
18063
  function loadDocsConfig(rootDir) {
18527
- const configPath = path31.join(rootDir, CONFIG_PATH);
18528
- if (!fs29.existsSync(configPath)) {
18064
+ const configPath = path30.join(rootDir, CONFIG_PATH);
18065
+ if (!fs28.existsSync(configPath)) {
18529
18066
  return { ...DEFAULT_CONFIG };
18530
18067
  }
18531
18068
  try {
18532
- const raw = fs29.readFileSync(configPath, "utf8");
18069
+ const raw = fs28.readFileSync(configPath, "utf8");
18533
18070
  const data = yaml17.load(raw);
18534
18071
  if (!data || !data.docs) return { ...DEFAULT_CONFIG };
18535
18072
  const docs = data.docs;
@@ -18553,40 +18090,40 @@ function loadDocsConfig(rootDir) {
18553
18090
  }
18554
18091
  }
18555
18092
  function loadScanIndex2(rootDir) {
18556
- const filePath = path31.join(rootDir, SCAN_INDEX_PATH);
18557
- if (!fs29.existsSync(filePath)) return null;
18093
+ const filePath = path30.join(rootDir, SCAN_INDEX_PATH);
18094
+ if (!fs28.existsSync(filePath)) return null;
18558
18095
  try {
18559
- const raw = fs29.readFileSync(filePath, "utf8");
18096
+ const raw = fs28.readFileSync(filePath, "utf8");
18560
18097
  return JSON.parse(raw);
18561
18098
  } catch {
18562
18099
  return null;
18563
18100
  }
18564
18101
  }
18565
18102
  function loadFlowIndex2(rootDir) {
18566
- const filePath = path31.join(rootDir, FLOW_INDEX_PATH);
18567
- if (!fs29.existsSync(filePath)) return null;
18103
+ const filePath = path30.join(rootDir, FLOW_INDEX_PATH);
18104
+ if (!fs28.existsSync(filePath)) return null;
18568
18105
  try {
18569
- const raw = fs29.readFileSync(filePath, "utf8");
18106
+ const raw = fs28.readFileSync(filePath, "utf8");
18570
18107
  return JSON.parse(raw);
18571
18108
  } catch {
18572
18109
  return null;
18573
18110
  }
18574
18111
  }
18575
18112
  function loadPortal(rootDir) {
18576
- const filePath = path31.join(rootDir, PORTAL_FILE);
18577
- if (!fs29.existsSync(filePath)) return null;
18113
+ const filePath = path30.join(rootDir, PORTAL_FILE);
18114
+ if (!fs28.existsSync(filePath)) return null;
18578
18115
  try {
18579
- const raw = fs29.readFileSync(filePath, "utf8");
18116
+ const raw = fs28.readFileSync(filePath, "utf8");
18580
18117
  return yaml17.load(raw);
18581
18118
  } catch {
18582
18119
  return null;
18583
18120
  }
18584
18121
  }
18585
18122
  function loadUniversityIndex(rootDir) {
18586
- const filePath = path31.join(rootDir, UNIVERSITY_INDEX_PATH);
18587
- if (!fs29.existsSync(filePath)) return null;
18123
+ const filePath = path30.join(rootDir, UNIVERSITY_INDEX_PATH);
18124
+ if (!fs28.existsSync(filePath)) return null;
18588
18125
  try {
18589
- const raw = fs29.readFileSync(filePath, "utf8");
18126
+ const raw = fs28.readFileSync(filePath, "utf8");
18590
18127
  return yaml17.load(raw);
18591
18128
  } catch {
18592
18129
  return null;
@@ -18652,14 +18189,14 @@ function isExcluded(entry, config) {
18652
18189
  return false;
18653
18190
  }
18654
18191
  function loadCustomPages(rootDir, customContentDir) {
18655
- const dir = path31.join(rootDir, customContentDir);
18656
- if (!fs29.existsSync(dir)) return [];
18192
+ const dir = path30.join(rootDir, customContentDir);
18193
+ if (!fs28.existsSync(dir)) return [];
18657
18194
  const pages = [];
18658
18195
  try {
18659
- const files = fs29.readdirSync(dir).filter((f) => f.endsWith(".md"));
18196
+ const files = fs28.readdirSync(dir).filter((f) => f.endsWith(".md"));
18660
18197
  for (const file of files) {
18661
18198
  try {
18662
- const raw = fs29.readFileSync(path31.join(dir, file), "utf8");
18199
+ const raw = fs28.readFileSync(path30.join(dir, file), "utf8");
18663
18200
  const slug = file.replace(/\.md$/, "");
18664
18201
  const parsed = parseFrontmatter(raw);
18665
18202
  if (parsed) {
@@ -18692,11 +18229,11 @@ function loadCustomPages(rootDir, customContentDir) {
18692
18229
  }
18693
18230
  function loadCustomPage(rootDir, slug, config) {
18694
18231
  const resolvedConfig = config || loadDocsConfig(rootDir);
18695
- const dir = path31.join(rootDir, resolvedConfig.customContent);
18696
- const filePath = path31.join(dir, `${slug}.md`);
18697
- if (!fs29.existsSync(filePath)) return null;
18232
+ const dir = path30.join(rootDir, resolvedConfig.customContent);
18233
+ const filePath = path30.join(dir, `${slug}.md`);
18234
+ if (!fs28.existsSync(filePath)) return null;
18698
18235
  try {
18699
- const raw = fs29.readFileSync(filePath, "utf8");
18236
+ const raw = fs28.readFileSync(filePath, "utf8");
18700
18237
  const parsed = parseFrontmatter(raw);
18701
18238
  if (parsed) {
18702
18239
  return {
@@ -18723,7 +18260,7 @@ function buildDocsManifest(rootDir, config) {
18723
18260
  const portal = loadPortal(rootDir);
18724
18261
  const customPages = loadCustomPages(rootDir, resolvedConfig.customContent);
18725
18262
  const uniIndex = loadUniversityIndex(rootDir);
18726
- const projectName = scanIndex?.$meta?.project || path31.basename(rootDir);
18263
+ const projectName = scanIndex?.$meta?.project || path30.basename(rootDir);
18727
18264
  const title = resolvedConfig.title || `${projectName} Docs`;
18728
18265
  const groups = [];
18729
18266
  const symbolCounts = {};
@@ -19679,8 +19216,8 @@ async function handleStreamsTool(name, args, ctx) {
19679
19216
  init_nomination_engine();
19680
19217
  init_event_stream();
19681
19218
  init_agent_loader();
19682
- import * as fs30 from "fs";
19683
- import * as path32 from "path";
19219
+ import * as fs29 from "fs";
19220
+ import * as path31 from "path";
19684
19221
  init_journal_loader();
19685
19222
  function getAmbientToolsList() {
19686
19223
  return [
@@ -19832,10 +19369,10 @@ async function handleAmbientTool(name, args, ctx) {
19832
19369
  });
19833
19370
  const surfacingConfig = loadSurfacingConfig(ctx.rootDir);
19834
19371
  nominations = applySurfacingRules(nominations, surfacingConfig).slice(0, limit);
19835
- const nominationsPath = path32.join(ctx.rootDir, ".paradigm/events/nominations.jsonl");
19836
- if (fs30.existsSync(nominationsPath)) {
19372
+ const nominationsPath = path31.join(ctx.rootDir, ".paradigm/events/nominations.jsonl");
19373
+ if (fs29.existsSync(nominationsPath)) {
19837
19374
  try {
19838
- const content = fs30.readFileSync(nominationsPath, "utf8");
19375
+ const content = fs29.readFileSync(nominationsPath, "utf8");
19839
19376
  const surfacedIds = new Set(nominations.map((n) => n.id));
19840
19377
  const lines = content.trim().split("\n").map((line) => {
19841
19378
  try {
@@ -19849,7 +19386,7 @@ async function handleAmbientTool(name, args, ctx) {
19849
19386
  return line;
19850
19387
  }
19851
19388
  });
19852
- fs30.writeFileSync(nominationsPath, lines.join("\n") + "\n", "utf8");
19389
+ fs29.writeFileSync(nominationsPath, lines.join("\n") + "\n", "utf8");
19853
19390
  } catch {
19854
19391
  }
19855
19392
  }
@@ -20073,7 +19610,7 @@ async function handleAmbientTool(name, args, ctx) {
20073
19610
  }
20074
19611
 
20075
19612
  // ../paradigm-mcp/src/tools/fallback-grep.ts
20076
- import * as path33 from "path";
19613
+ import * as path32 from "path";
20077
19614
  import { execSync as execSync8 } from "child_process";
20078
19615
  function grepForReferences(rootDir, symbol, options = {}) {
20079
19616
  const { maxResults = 20 } = options;
@@ -20102,7 +19639,7 @@ function grepForReferences(rootDir, symbol, options = {}) {
20102
19639
  const match = line.match(/^(.+?):(\d+):(.*)$/);
20103
19640
  if (match) {
20104
19641
  const [, filePath, lineNum, content] = match;
20105
- const relativePath = path33.relative(rootDir, filePath);
19642
+ const relativePath = path32.relative(rootDir, filePath);
20106
19643
  let context2 = "unknown";
20107
19644
  if (relativePath.includes(".purpose") || relativePath.includes("portal.yaml")) {
20108
19645
  context2 = "purpose";
@@ -21155,10 +20692,10 @@ Update command:
21155
20692
  trackToolCall(noWsText.length, name);
21156
20693
  return { content: [{ type: "text", text: noWsText }] };
21157
20694
  }
21158
- const { rebuildStaticFiles: rebuildStaticFiles2 } = await import("./reindex-KFUPB3ES.js");
20695
+ const { rebuildStaticFiles: rebuildStaticFiles2 } = await import("./reindex-U2HEB6GW.js");
21159
20696
  const memberResults = [];
21160
20697
  for (const member of ctx.workspace.config.members) {
21161
- const memberAbsPath = path34.resolve(path34.dirname(ctx.workspace.workspacePath), member.path);
20698
+ const memberAbsPath = path33.resolve(path33.dirname(ctx.workspace.workspacePath), member.path);
21162
20699
  try {
21163
20700
  const result = await rebuildStaticFiles2(memberAbsPath);
21164
20701
  memberResults.push({