@knowsuchagency/fulcrum 4.14.2 → 5.0.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/bin/fulcrum.js CHANGED
@@ -951,10 +951,6 @@ var init_errors = __esm(() => {
951
951
  });
952
952
 
953
953
  // cli/src/client.ts
954
- var exports_client = {};
955
- __export(exports_client, {
956
- FulcrumClient: () => FulcrumClient
957
- });
958
954
  import { readFileSync } from "fs";
959
955
  import { basename } from "path";
960
956
 
@@ -43618,8 +43614,7 @@ var init_types4 = __esm(() => {
43618
43614
  "messaging",
43619
43615
  "assistant",
43620
43616
  "caldav",
43621
- "memory",
43622
- "board"
43617
+ "memory"
43623
43618
  ]);
43624
43619
  AgentTypeSchema = exports_external.enum(["claude", "opencode"]);
43625
43620
  });
@@ -44581,27 +44576,6 @@ var init_registry = __esm(() => {
44581
44576
  category: "jobs",
44582
44577
  keywords: ["job", "timer", "run", "trigger", "execute", "now"],
44583
44578
  defer_loading: true
44584
- },
44585
- {
44586
- name: "board_read",
44587
- description: "Read the agent coordination board for recent messages from other agents",
44588
- category: "board",
44589
- keywords: ["board", "coordination", "agent", "read", "messages", "status", "conflict"],
44590
- defer_loading: false
44591
- },
44592
- {
44593
- name: "board_post",
44594
- description: "Post a message to the agent coordination board (claims, status, warnings)",
44595
- category: "board",
44596
- keywords: ["board", "coordination", "agent", "post", "claim", "resource", "port", "announce"],
44597
- defer_loading: false
44598
- },
44599
- {
44600
- name: "board_check",
44601
- description: "Check if a resource is claimed by another agent on the coordination board",
44602
- category: "board",
44603
- keywords: ["board", "coordination", "agent", "check", "claim", "resource", "port", "conflict"],
44604
- defer_loading: false
44605
44579
  }
44606
44580
  ];
44607
44581
  });
@@ -46792,326 +46766,6 @@ var init_jobs = __esm(() => {
46792
46766
  JobScopeSchema = exports_external.enum(["all", "user", "system"]);
46793
46767
  });
46794
46768
 
46795
- // cli/src/board/types.ts
46796
- var DEFAULT_TTLS;
46797
- var init_types6 = __esm(() => {
46798
- DEFAULT_TTLS = {
46799
- claim: 7200,
46800
- release: 300,
46801
- info: 3600,
46802
- warning: 7200,
46803
- request: 14400
46804
- };
46805
- });
46806
-
46807
- // cli/src/board/index.ts
46808
- import { existsSync as existsSync7, mkdirSync as mkdirSync5, readdirSync, readFileSync as readFileSync6, writeFileSync as writeFileSync5, unlinkSync as unlinkSync3, renameSync as renameSync3 } from "fs";
46809
- import { join as join7 } from "path";
46810
- import { homedir as homedir4, tmpdir } from "os";
46811
- function getGlobalFulcrumDir() {
46812
- if (process.env.FULCRUM_DIR) {
46813
- return process.env.FULCRUM_DIR.replace(/^~/, homedir4());
46814
- }
46815
- return join7(homedir4(), ".fulcrum");
46816
- }
46817
- function getBoardDir() {
46818
- return join7(getGlobalFulcrumDir(), "board", "messages");
46819
- }
46820
- function getRefsDir() {
46821
- return join7(getGlobalFulcrumDir(), "board", "refs");
46822
- }
46823
- function ensureBoardDirs() {
46824
- mkdirSync5(getBoardDir(), { recursive: true });
46825
- mkdirSync5(getRefsDir(), { recursive: true });
46826
- }
46827
- function generateId() {
46828
- return Math.random().toString(36).substring(2, 6);
46829
- }
46830
- function detectAgent() {
46831
- if (process.env.CLAUDE_CODE)
46832
- return "claude";
46833
- if (process.env.CLAUDE_CODE_ENTRY_POINT)
46834
- return "claude";
46835
- return "unknown";
46836
- }
46837
- async function getTaskContext() {
46838
- const taskId = process.env.FULCRUM_TASK_ID;
46839
- if (!taskId)
46840
- return {};
46841
- try {
46842
- const { FulcrumClient: FulcrumClient2 } = await Promise.resolve().then(() => (init_client(), exports_client));
46843
- const client = new FulcrumClient2;
46844
- const task = await client.getTask(taskId);
46845
- return {
46846
- taskId,
46847
- taskTitle: task.title,
46848
- project: task.projectId ?? undefined,
46849
- repository: task.repoName ?? undefined,
46850
- worktree: task.worktreePath ?? undefined
46851
- };
46852
- } catch {
46853
- return { taskId };
46854
- }
46855
- }
46856
- function parseDuration(duration5) {
46857
- let seconds = 0;
46858
- const hourMatch = duration5.match(/(\d+)h/);
46859
- const minuteMatch = duration5.match(/(\d+)m/);
46860
- const secondMatch = duration5.match(/(\d+)s/);
46861
- if (hourMatch)
46862
- seconds += parseInt(hourMatch[1], 10) * 3600;
46863
- if (minuteMatch)
46864
- seconds += parseInt(minuteMatch[1], 10) * 60;
46865
- if (secondMatch)
46866
- seconds += parseInt(secondMatch[1], 10);
46867
- if (seconds === 0 && /^\d+$/.test(duration5)) {
46868
- seconds = parseInt(duration5, 10);
46869
- }
46870
- return seconds || 3600;
46871
- }
46872
- function readBoard(options = {}) {
46873
- const dir = getBoardDir();
46874
- if (!existsSync7(dir))
46875
- return [];
46876
- const now = Date.now();
46877
- const sinceMs = options.since ? now - parseDuration(options.since) * 1000 : now - 3600000;
46878
- const limit = options.limit ?? 50;
46879
- let entries;
46880
- try {
46881
- entries = readdirSync(dir).filter((f3) => f3.endsWith(".json")).sort();
46882
- } catch {
46883
- return [];
46884
- }
46885
- const messages = [];
46886
- const expired = [];
46887
- for (const filename of entries) {
46888
- const tsStr = filename.split("-")[0];
46889
- const fileTs = parseInt(tsStr, 10);
46890
- const filePath = join7(dir, filename);
46891
- try {
46892
- const content = readFileSync6(filePath, "utf-8");
46893
- const msg = JSON.parse(content);
46894
- const msgTs = new Date(msg.timestamp).getTime();
46895
- const expiresAt = msgTs + msg.ttl * 1000;
46896
- if (expiresAt < now) {
46897
- expired.push(filePath);
46898
- continue;
46899
- }
46900
- if (fileTs < sinceMs)
46901
- continue;
46902
- if (options.type && msg.type !== options.type)
46903
- continue;
46904
- if (options.project && msg.project !== options.project)
46905
- continue;
46906
- if (options.tag && (!msg.tags || !msg.tags.includes(options.tag)))
46907
- continue;
46908
- messages.push(msg);
46909
- } catch {}
46910
- }
46911
- for (const path of expired) {
46912
- try {
46913
- unlinkSync3(path);
46914
- } catch {}
46915
- }
46916
- return messages.reverse().slice(0, limit);
46917
- }
46918
- async function postMessage(input) {
46919
- ensureBoardDirs();
46920
- const id = generateId();
46921
- const now = new Date;
46922
- const type = input.type ?? "info";
46923
- const ttl = input.ttl ?? DEFAULT_TTLS[type];
46924
- const context = await getTaskContext();
46925
- const agent = detectAgent();
46926
- const message = {
46927
- id,
46928
- timestamp: now.toISOString(),
46929
- type,
46930
- agent,
46931
- ...context,
46932
- ttl,
46933
- body: input.body,
46934
- tags: input.tags
46935
- };
46936
- if (input.refContent) {
46937
- const refFilename = `${id}-ref.txt`;
46938
- const refPath = join7(getRefsDir(), refFilename);
46939
- writeFileSync5(refPath, input.refContent, "utf-8");
46940
- message.refs = [refFilename];
46941
- }
46942
- const filename = `${now.getTime()}-${id}.json`;
46943
- const finalPath = join7(getBoardDir(), filename);
46944
- const tempPath = join7(tmpdir(), `fulcrum-board-${filename}`);
46945
- writeFileSync5(tempPath, JSON.stringify(message, null, 2), "utf-8");
46946
- renameSync3(tempPath, finalPath);
46947
- return message;
46948
- }
46949
- function checkResource(resource) {
46950
- const dir = getBoardDir();
46951
- if (!existsSync7(dir))
46952
- return null;
46953
- const now = Date.now();
46954
- let entries;
46955
- try {
46956
- entries = readdirSync(dir).filter((f3) => f3.endsWith(".json")).sort().reverse();
46957
- } catch {
46958
- return null;
46959
- }
46960
- for (const filename of entries) {
46961
- const filePath = join7(dir, filename);
46962
- try {
46963
- const content = readFileSync6(filePath, "utf-8");
46964
- const msg = JSON.parse(content);
46965
- if (msg.type !== "claim")
46966
- continue;
46967
- const msgTs = new Date(msg.timestamp).getTime();
46968
- if (msgTs + msg.ttl * 1000 < now)
46969
- continue;
46970
- if (msg.tags && msg.tags.includes(resource)) {
46971
- return msg;
46972
- }
46973
- } catch {}
46974
- }
46975
- return null;
46976
- }
46977
- function releaseAllByTask(taskId) {
46978
- const dir = getBoardDir();
46979
- if (!existsSync7(dir))
46980
- return 0;
46981
- let entries;
46982
- try {
46983
- entries = readdirSync(dir).filter((f3) => f3.endsWith(".json"));
46984
- } catch {
46985
- return 0;
46986
- }
46987
- let deleted = 0;
46988
- for (const filename of entries) {
46989
- const filePath = join7(dir, filename);
46990
- try {
46991
- const content = readFileSync6(filePath, "utf-8");
46992
- const msg = JSON.parse(content);
46993
- if (msg.type === "claim" && msg.taskId === taskId) {
46994
- unlinkSync3(filePath);
46995
- deleted++;
46996
- }
46997
- } catch {}
46998
- }
46999
- return deleted;
47000
- }
47001
- function cleanBoard(all) {
47002
- const dir = getBoardDir();
47003
- if (!existsSync7(dir))
47004
- return 0;
47005
- let entries;
47006
- try {
47007
- entries = readdirSync(dir).filter((f3) => f3.endsWith(".json"));
47008
- } catch {
47009
- return 0;
47010
- }
47011
- const now = Date.now();
47012
- let deleted = 0;
47013
- for (const filename of entries) {
47014
- const filePath = join7(dir, filename);
47015
- if (all) {
47016
- try {
47017
- unlinkSync3(filePath);
47018
- deleted++;
47019
- } catch {}
47020
- continue;
47021
- }
47022
- try {
47023
- const content = readFileSync6(filePath, "utf-8");
47024
- const msg = JSON.parse(content);
47025
- const msgTs = new Date(msg.timestamp).getTime();
47026
- if (msgTs + msg.ttl * 1000 < now) {
47027
- unlinkSync3(filePath);
47028
- deleted++;
47029
- }
47030
- } catch {
47031
- try {
47032
- unlinkSync3(filePath);
47033
- deleted++;
47034
- } catch {}
47035
- }
47036
- }
47037
- if (all) {
47038
- const refsDir = getRefsDir();
47039
- if (existsSync7(refsDir)) {
47040
- try {
47041
- for (const ref of readdirSync(refsDir)) {
47042
- try {
47043
- unlinkSync3(join7(refsDir, ref));
47044
- deleted++;
47045
- } catch {}
47046
- }
47047
- } catch {}
47048
- }
47049
- }
47050
- return deleted;
47051
- }
47052
- var init_board = __esm(() => {
47053
- init_types6();
47054
- });
47055
-
47056
- // cli/src/mcp/tools/board.ts
47057
- var registerBoardTools = (server, _client) => {
47058
- server.tool("board_read", "Read the agent coordination board. Returns recent messages from other agents working in the same project. Use before claiming resources (ports, services) to avoid conflicts.", {
47059
- since: exports_external.optional(exports_external.string()).describe('Time window, e.g. "1h", "30m", "2h". Default: "1h"'),
47060
- type: exports_external.optional(exports_external.enum(["claim", "release", "info", "warning", "request"])).describe("Filter by message type"),
47061
- project: exports_external.optional(exports_external.string()).describe("Filter by project name"),
47062
- tag: exports_external.optional(exports_external.string()).describe('Filter by tag, e.g. "port:5173"'),
47063
- limit: exports_external.optional(exports_external.number().min(1).max(200)).describe("Max messages to return (default: 50)")
47064
- }, async ({ since, type, project, tag, limit }) => {
47065
- try {
47066
- const messages = readBoard({
47067
- since,
47068
- type,
47069
- project,
47070
- tag,
47071
- limit
47072
- });
47073
- return formatSuccess(messages);
47074
- } catch (err) {
47075
- return handleToolError(err);
47076
- }
47077
- });
47078
- server.tool("board_post", "Post a message to the agent coordination board. Announce resource claims, share status updates, or coordinate with other agents working on the same project.", {
47079
- body: exports_external.string().describe("Message body describing what you are doing or claiming"),
47080
- type: exports_external.optional(exports_external.enum(["claim", "release", "info", "warning", "request"])).describe('Message type. Default: "info". Use "claim" to reserve resources, "release" to free them.'),
47081
- tags: exports_external.optional(exports_external.array(exports_external.string())).describe('Tags for categorization and resource matching, e.g. ["port:5173", "dev-server"]'),
47082
- ttl: exports_external.optional(exports_external.number()).describe("Time-to-live in seconds. Defaults vary by type: claim=7200, release=300, info=3600"),
47083
- refContent: exports_external.optional(exports_external.string()).describe("Large content to store as a ref file (e.g., error logs)")
47084
- }, async ({ body, type, tags, ttl, refContent }) => {
47085
- try {
47086
- const message = await postMessage({
47087
- body,
47088
- type,
47089
- tags,
47090
- ttl,
47091
- refContent
47092
- });
47093
- return formatSuccess(message);
47094
- } catch (err) {
47095
- return handleToolError(err);
47096
- }
47097
- });
47098
- server.tool("board_check", "Check if a resource is claimed by another agent. Returns the active claim if found, null if the resource is free. Use before starting dev servers, database operations, etc.", {
47099
- resource: exports_external.string().describe('Resource tag to check, e.g. "port:5173", "db:migration"')
47100
- }, async ({ resource }) => {
47101
- try {
47102
- const claim = checkResource(resource);
47103
- return formatSuccess(claim ? { claimed: true, claim } : { claimed: false });
47104
- } catch (err) {
47105
- return handleToolError(err);
47106
- }
47107
- });
47108
- };
47109
- var init_board2 = __esm(() => {
47110
- init_zod2();
47111
- init_utils();
47112
- init_board();
47113
- });
47114
-
47115
46769
  // cli/src/mcp/tools/index.ts
47116
46770
  function registerTools(server, client) {
47117
46771
  registerCoreTools(server, client);
@@ -47134,7 +46788,6 @@ function registerTools(server, client) {
47134
46788
  registerMemoryFileTools(server, client);
47135
46789
  registerSearchTools(server, client);
47136
46790
  registerJobTools(server, client);
47137
- registerBoardTools(server, client);
47138
46791
  }
47139
46792
  var init_tools = __esm(() => {
47140
46793
  init_core5();
@@ -47157,7 +46810,6 @@ var init_tools = __esm(() => {
47157
46810
  init_messaging();
47158
46811
  init_search();
47159
46812
  init_jobs();
47160
- init_board2();
47161
46813
  init_types4();
47162
46814
  });
47163
46815
 
@@ -47176,7 +46828,7 @@ async function runMcpServer(urlOverride, portOverride) {
47176
46828
  const client = new FulcrumClient(urlOverride, portOverride);
47177
46829
  const server = new McpServer({
47178
46830
  name: "fulcrum",
47179
- version: "4.14.2"
46831
+ version: "5.0.0"
47180
46832
  });
47181
46833
  registerTools(server, client);
47182
46834
  const transport = new StdioServerTransport;
@@ -48599,15 +48251,6 @@ function setJsonOutput(value) {
48599
48251
  function isJsonOutput() {
48600
48252
  return jsonOutput;
48601
48253
  }
48602
- function prettyLog(type, message) {
48603
- const prefixes = {
48604
- success: "\u2713",
48605
- info: "\u2192",
48606
- error: "\u2717",
48607
- warning: "\u26A0"
48608
- };
48609
- console.log(`${prefixes[type]} ${message}`);
48610
- }
48611
48254
  function output(data) {
48612
48255
  const response = {
48613
48256
  success: true,
@@ -49534,7 +49177,7 @@ var marketplace_default = `{
49534
49177
  "name": "fulcrum",
49535
49178
  "source": "./",
49536
49179
  "description": "Task orchestration for Claude Code",
49537
- "version": "4.14.2",
49180
+ "version": "5.0.0",
49538
49181
  "skills": [
49539
49182
  "./skills/fulcrum"
49540
49183
  ],
@@ -49557,7 +49200,7 @@ var marketplace_default = `{
49557
49200
  var plugin_default = `{
49558
49201
  "name": "fulcrum",
49559
49202
  "description": "Fulcrum task orchestration for Claude Code",
49560
- "version": "4.14.2",
49203
+ "version": "5.0.0",
49561
49204
  "author": {
49562
49205
  "name": "Fulcrum"
49563
49206
  },
@@ -49573,10 +49216,6 @@ var hooks_default = `{
49573
49216
  "Stop": [
49574
49217
  {
49575
49218
  "hooks": [
49576
- {
49577
- "type": "command",
49578
- "command": "fulcrum board release-all 2>/dev/null || true"
49579
- },
49580
49219
  {
49581
49220
  "type": "command",
49582
49221
  "command": "fulcrum current-task review 2>/dev/null || true"
@@ -49726,42 +49365,6 @@ fulcrum notify "Task Complete" "Implemented the new feature and created PR #123"
49726
49365
  fulcrum notify "Need Input" "Which approach should I use for the database migration?"
49727
49366
  \`\`\`
49728
49367
 
49729
- ## Agent Coordination Board
49730
-
49731
- When multiple agents work on the same project in separate worktrees, use the coordination board to avoid conflicts (port collisions, concurrent migrations, etc.).
49732
-
49733
- ### When to Use
49734
-
49735
- - **Before starting a dev server** \u2014 check if the port is already claimed
49736
- - **Before running database migrations** \u2014 check if another agent is migrating
49737
- - **When using shared resources** \u2014 claim them first, release when done
49738
-
49739
- ### CLI Commands
49740
-
49741
- \`\`\`bash
49742
- fulcrum board # Read recent messages (last 1h)
49743
- fulcrum board read --since 2h # Custom time window
49744
- fulcrum board read --type claim # Filter by type
49745
- fulcrum board read --tag port:5173 # Filter by tag
49746
-
49747
- fulcrum board post "Using port 5173" --type claim --tag port:5173
49748
- fulcrum board post "Migration complete" --type info
49749
-
49750
- fulcrum board check port:5173 # Check if resource is claimed
49751
-
49752
- fulcrum board release-all # Release all your claims (auto-runs on Stop)
49753
-
49754
- fulcrum board clean # Remove expired messages
49755
- fulcrum board clean --all # Remove ALL messages
49756
- \`\`\`
49757
-
49758
- ### Best Practices
49759
-
49760
- 1. **Always check before claiming** \u2014 \`fulcrum board check port:<N>\` before starting a dev server
49761
- 2. **Always release when done** \u2014 Post a \`release\` message or use \`fulcrum board release-all\`
49762
- 3. **Claims auto-expire** \u2014 TTL is 2 hours for claims, so crashes won't permanently block resources
49763
- 4. **The Stop hook auto-releases** \u2014 When your session ends, claims are released automatically
49764
-
49765
49368
  ## Global Options
49766
49369
 
49767
49370
  - \`--port=<port>\` \u2014 Server port (default: 7777)
@@ -50609,7 +50212,7 @@ function compareVersions(v1, v2) {
50609
50212
  var package_default = {
50610
50213
  name: "@knowsuchagency/fulcrum",
50611
50214
  private: true,
50612
- version: "4.14.2",
50215
+ version: "5.0.0",
50613
50216
  description: "Harness Attention. Orchestrate Agents. Ship.",
50614
50217
  license: "PolyForm-Perimeter-1.0.0",
50615
50218
  type: "module",
@@ -50625,7 +50228,7 @@ var package_default = {
50625
50228
  "db:studio": "drizzle-kit studio"
50626
50229
  },
50627
50230
  dependencies: {
50628
- "@anthropic-ai/claude-agent-sdk": "0.2.110",
50231
+ "@anthropic-ai/claude-agent-sdk": "0.2.114",
50629
50232
  "@atlaskit/pragmatic-drag-and-drop": "^1.7.7",
50630
50233
  "@atlaskit/pragmatic-drag-and-drop-hitbox": "^1.1.0",
50631
50234
  "@azurity/pure-nerd-font": "^3.0.5",
@@ -51353,176 +50956,6 @@ var mcpCommand = defineCommand({
51353
50956
  }
51354
50957
  });
51355
50958
 
51356
- // cli/src/commands/board.ts
51357
- init_board();
51358
- function formatMessage(msg) {
51359
- const age = getAge(msg.timestamp);
51360
- const typeColor = {
51361
- claim: "[CLAIM]",
51362
- release: "[RELEASE]",
51363
- info: "[INFO]",
51364
- warning: "[WARNING]",
51365
- request: "[REQUEST]"
51366
- };
51367
- const prefix = typeColor[msg.type] ?? `[${msg.type.toUpperCase()}]`;
51368
- const agent = msg.agent !== "unknown" ? ` (${msg.agent})` : "";
51369
- const task = msg.taskTitle ? ` | ${msg.taskTitle}` : "";
51370
- const tags = msg.tags?.length ? ` [${msg.tags.join(", ")}]` : "";
51371
- console.log(`${prefix} ${msg.body}${agent}${task}${tags} (${age} ago)`);
51372
- }
51373
- function getAge(timestamp) {
51374
- const ms = Date.now() - new Date(timestamp).getTime();
51375
- const seconds = Math.floor(ms / 1000);
51376
- if (seconds < 60)
51377
- return `${seconds}s`;
51378
- const minutes = Math.floor(seconds / 60);
51379
- if (minutes < 60)
51380
- return `${minutes}m`;
51381
- const hours = Math.floor(minutes / 60);
51382
- const remainingMinutes = minutes % 60;
51383
- if (remainingMinutes > 0)
51384
- return `${hours}h${remainingMinutes}m`;
51385
- return `${hours}h`;
51386
- }
51387
- var readCommand = defineCommand({
51388
- meta: { name: "read", description: "Read recent messages from the coordination board" },
51389
- args: {
51390
- since: { type: "string", description: "Time window (e.g., 1h, 30m, 2h). Default: 1h" },
51391
- type: { type: "string", description: "Filter by type: claim, release, info, warning, request" },
51392
- project: { type: "string", description: "Filter by project name" },
51393
- tag: { type: "string", description: "Filter by tag (e.g., port:5173)" },
51394
- limit: { type: "string", description: "Max messages to return (default: 50)" },
51395
- json: { type: "boolean", description: "Output as JSON" }
51396
- },
51397
- async run({ args }) {
51398
- setupJsonOutput(args);
51399
- const messages = readBoard({
51400
- since: args.since,
51401
- type: args.type,
51402
- project: args.project,
51403
- tag: args.tag,
51404
- limit: args.limit ? parseInt(args.limit, 10) : undefined
51405
- });
51406
- if (isJsonOutput()) {
51407
- output(messages);
51408
- } else {
51409
- if (messages.length === 0) {
51410
- prettyLog("info", "No messages on the board");
51411
- } else {
51412
- for (const msg of messages) {
51413
- formatMessage(msg);
51414
- }
51415
- }
51416
- }
51417
- }
51418
- });
51419
- var postCommand = defineCommand({
51420
- meta: { name: "post", description: "Post a message to the coordination board" },
51421
- args: {
51422
- body: { type: "positional", description: "Message body", required: true },
51423
- type: { type: "string", description: "Message type: claim, release, info, warning, request. Default: info" },
51424
- tag: { type: "string", description: "Add a tag (repeatable with comma separation, e.g., port:5173,dev-server)" },
51425
- ttl: { type: "string", description: "TTL in seconds (overrides default for type)" },
51426
- json: { type: "boolean", description: "Output as JSON" }
51427
- },
51428
- async run({ args }) {
51429
- setupJsonOutput(args);
51430
- const tags = args.tag ? args.tag.split(",").map((t2) => t2.trim()).filter(Boolean) : undefined;
51431
- const message = await postMessage({
51432
- body: args.body,
51433
- type: args.type ?? "info",
51434
- tags,
51435
- ttl: args.ttl ? parseInt(args.ttl, 10) : undefined
51436
- });
51437
- if (isJsonOutput()) {
51438
- output(message);
51439
- } else {
51440
- prettyLog("success", `Posted: ${message.body}`);
51441
- }
51442
- }
51443
- });
51444
- var checkCommand = defineCommand({
51445
- meta: { name: "check", description: "Check if a resource is claimed by another agent" },
51446
- args: {
51447
- resource: { type: "positional", description: "Resource tag to check (e.g., port:5173)", required: true },
51448
- json: { type: "boolean", description: "Output as JSON" }
51449
- },
51450
- async run({ args }) {
51451
- setupJsonOutput(args);
51452
- const claim = checkResource(args.resource);
51453
- if (isJsonOutput()) {
51454
- output(claim ? { claimed: true, claim } : { claimed: false });
51455
- } else {
51456
- if (claim) {
51457
- prettyLog("warning", `Resource "${args.resource}" is claimed`);
51458
- formatMessage(claim);
51459
- process.exit(0);
51460
- } else {
51461
- prettyLog("success", `Resource "${args.resource}" is free`);
51462
- process.exit(1);
51463
- }
51464
- }
51465
- }
51466
- });
51467
- var releaseAllCommand = defineCommand({
51468
- meta: { name: "release-all", description: "Release all claims by the current task" },
51469
- args: {
51470
- json: { type: "boolean", description: "Output as JSON" }
51471
- },
51472
- async run({ args }) {
51473
- setupJsonOutput(args);
51474
- const taskId = process.env.FULCRUM_TASK_ID;
51475
- if (!taskId) {
51476
- if (isJsonOutput()) {
51477
- output({ released: 0, message: "No FULCRUM_TASK_ID set" });
51478
- } else {
51479
- prettyLog("info", "No FULCRUM_TASK_ID set \u2014 nothing to release");
51480
- }
51481
- return;
51482
- }
51483
- const count = releaseAllByTask(taskId);
51484
- if (isJsonOutput()) {
51485
- output({ released: count, taskId });
51486
- } else {
51487
- if (count > 0) {
51488
- prettyLog("success", `Released ${count} claim(s) for task ${taskId}`);
51489
- } else {
51490
- prettyLog("info", "No active claims to release");
51491
- }
51492
- }
51493
- }
51494
- });
51495
- var cleanCommand = defineCommand({
51496
- meta: { name: "clean", description: "Remove expired messages from the board" },
51497
- args: {
51498
- all: { type: "boolean", description: "Remove ALL messages (not just expired)" },
51499
- json: { type: "boolean", description: "Output as JSON" }
51500
- },
51501
- async run({ args }) {
51502
- setupJsonOutput(args);
51503
- const count = cleanBoard(args.all);
51504
- if (isJsonOutput()) {
51505
- output({ deleted: count });
51506
- } else {
51507
- if (count > 0) {
51508
- prettyLog("success", `Removed ${count} message(s)`);
51509
- } else {
51510
- prettyLog("info", "Nothing to clean");
51511
- }
51512
- }
51513
- }
51514
- });
51515
- var boardCommand = defineCommand({
51516
- meta: { name: "board", description: "Agent coordination board for multi-agent environments" },
51517
- subCommands: {
51518
- read: readCommand,
51519
- post: postCommand,
51520
- check: checkCommand,
51521
- "release-all": releaseAllCommand,
51522
- clean: cleanCommand
51523
- }
51524
- });
51525
-
51526
50959
  // cli/src/commands/migrate-from-vibora.ts
51527
50960
  init_server();
51528
50961
  async function handleMigrateFromViboraCommand(flags) {
@@ -51617,7 +51050,6 @@ var main = defineCommand({
51617
51050
  config: configCommand,
51618
51051
  opencode: opencodeCommand,
51619
51052
  claude: claudeCommand,
51620
- board: boardCommand,
51621
51053
  notifications: notificationsCommand,
51622
51054
  notify: notifyCommand,
51623
51055
  up: upCommand,