wogiflow 2.4.4 → 2.5.1

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/lib/workspace.js CHANGED
@@ -328,14 +328,24 @@ function generateWorkspaceConfig(workspaceName, members) {
328
328
  sync: {
329
329
  autoOnSessionStart: true,
330
330
  autoAfterTaskComplete: true
331
+ },
332
+ channels: {
333
+ enabled: true,
334
+ basePort: 8801,
335
+ members: {}
331
336
  }
332
337
  };
333
338
 
339
+ let port = config.channels.basePort;
340
+ if (port + members.length - 1 > 65535) {
341
+ throw new Error(`Channel port range ${port}-${port + members.length - 1} exceeds maximum port 65535. Reduce basePort or number of members.`);
342
+ }
334
343
  for (const member of members) {
335
344
  config.members[member.name] = {
336
345
  path: `./${member.name}`,
337
346
  role: member.role
338
347
  };
348
+ config.channels.members[member.name] = { port: port++ };
339
349
  }
340
350
 
341
351
  return config;
@@ -546,49 +556,43 @@ ${Object.entries(manifest.members).map(([name, m]) => {
546
556
  }).join('\n')}
547
557
  - **Both/all repos**: api contract, schema change, integration, full-stack, end-to-end
548
558
 
549
- ### Step 3: Execute
550
-
551
- **Single-repo task — spawn one sub-agent:**
552
- \`\`\`
553
- Use the Agent tool:
554
- prompt: "You are working in the <REPO> repository.
555
- Stack: <STACK>
556
- Task: <TASK DESCRIPTION>
559
+ ### Step 3: Dispatch via Channels
557
560
 
558
- Project rules (read from <REPO>/.workflow/state/decisions.md):
559
- <PASTE DECISIONS CONTENT>
561
+ Each worker repo runs a full Claude Code session with its own CLAUDE.md, hooks, and WogiFlow pipeline. You dispatch tasks by sending HTTP requests to their channel ports. **Do NOT use the Agent tool for implementation** — use channels for full enforcement.
560
562
 
561
- After completing: commit your changes with a descriptive message."
563
+ **Worker Channel Ports:**
564
+ ${Object.entries(config.channels?.members || {}).map(([name, ch]) => `- **${name}**: \`http://localhost:${ch.port}\``).join('\n')}
562
565
 
563
- The sub-agent runs with the full codebase of that repo available.
564
- It follows that repo's own WogiFlow rules, decisions, and patterns.
566
+ **Check if workers are running:**
567
+ \`\`\`bash
568
+ ${Object.entries(config.channels?.members || {}).map(([name, ch]) => `curl -s http://localhost:${ch.port}/health`).join('\n')}
565
569
  \`\`\`
566
570
 
567
- **Cross-repo task sequential delegation:**
568
- 1. Read the contract from \`.workspace/contracts/\` (if exists)
569
- 2. If the API contract needs updating, update it first
570
- 3. Spawn provider sub-agent (${providers.join(' or ')}) — implement the API side
571
- 4. Read what the provider changed (from its git diff or commit message)
572
- 5. Write a message to \`.workspace/messages/\` describing the change
573
- 6. Spawn consumer sub-agent (${consumers.join(' or ')}) — implement the client side, include the message as context
574
- 7. Verify both sides work together
575
-
576
- **Bug investigation — parallel agents:**
577
- \`\`\`
578
- Spawn ${memberNames.length} agents IN PARALLEL (single message with multiple Agent tool calls):
571
+ If a worker is down, tell the user: "Start the ${'{'}repo{'}'} worker: \`cd ${'{'}repo{'}'}/ && flow workspace start\`"
579
572
 
580
- Agent 1 (${memberNames[0]}):
581
- "Investigate this bug in ${memberNames[0]}: <BUG DESCRIPTION>
582
- Check: recent changes, error logs, relevant code.
583
- Report: Is the issue on YOUR side? What did you find?"
573
+ **Single-repo task:**
574
+ 1. Create task in the repo's ready.json using \`decomposeToRepoTasks()\` or directly
575
+ 2. Dispatch: \`curl -s -X POST http://localhost:${'{'}port{'}'} -d "/wogi-start ${'{'}taskId${'}'}"\`
576
+ 3. The worker's full WogiFlow pipeline handles the rest (explore, spec, implement, verify)
577
+ 4. Monitor: check \`.workspace/messages/\` for a \`task-complete\` message
584
578
 
585
- ${memberNames.length > 1 ? `Agent 2 (${memberNames[1]}):
586
- "Investigate this bug in ${memberNames[1]}: <BUG DESCRIPTION>
587
- Check: recent changes, error logs, relevant code.
588
- Report: Is the issue on YOUR side? What did you find?"` : ''}
589
-
590
- Then synthesize the findings and route the fix to the correct repo.
579
+ **Cross-repo task:**
580
+ 1. Read the contract from \`.workspace/contracts/\` (if exists)
581
+ 2. If the API contract needs updating, update it first
582
+ 3. Create tasks in each repo's ready.json (provider gets P0 priority)
583
+ 4. Dispatch to provider first: \`curl -s -X POST http://localhost:${providers[0] ? config.channels?.members?.[providers[0]]?.port || '{port}' : '{port}'} -d "/wogi-start ${'{'}providerTaskId${'}'}"\`
584
+ 5. Wait for provider completion message in \`.workspace/messages/\`
585
+ 6. Then dispatch to consumer: \`curl -s -X POST http://localhost:${consumers[0] ? config.channels?.members?.[consumers[0]]?.port || '{port}' : '{port}'} -d "/wogi-start ${'{'}consumerTaskId${'}'}"\`
586
+ 7. Wait for consumer completion, then verify integration
587
+
588
+ **Bug investigation — dispatch to all workers:**
589
+ \`\`\`bash
590
+ # Send investigation request to all workers in parallel
591
+ ${Object.entries(config.channels?.members || {}).map(([name, ch]) =>
592
+ `curl -s -X POST http://localhost:${ch.port} -d "Investigate: <BUG_DESCRIPTION>. Check recent changes, error logs, relevant code. Report back via workspace message."`
593
+ ).join('\n')}
591
594
  \`\`\`
595
+ Then read responses from \`.workspace/messages/\` and synthesize findings.
592
596
 
593
597
  ## Reading Member State (What to Read, When)
594
598
 
@@ -637,6 +641,51 @@ When spawning a sub-agent, check for pending messages to that repo and include t
637
641
  Shared API contracts: \`.workspace/contracts/\`
638
642
  When a provider changes an endpoint, update the contract BEFORE the consumer implements.
639
643
 
644
+ ## Peer Communication (Worker ↔ Worker)
645
+
646
+ Workers can talk directly to each other — no manager bottleneck. Each worker knows its peers' channel ports.
647
+
648
+ A worker asking its peer a question:
649
+ \`\`\`bash
650
+ curl -s -X POST http://localhost:{peer_port} -H "X-Wogi-From: {my_repo}" -d "Is the POST /users endpoint ready? What's the expected payload shape?"
651
+ \`\`\`
652
+
653
+ The peer receives this as a channel event, reads its codebase to answer, and can reply back the same way. This is useful when:
654
+ - Frontend needs to know the exact API shape before implementing
655
+ - Backend wants to know which fields the frontend actually uses
656
+ - Any repo needs real-time coordination without going through the manager
657
+
658
+ Workers also have a \`workspace_send_message\` MCP tool that handles this automatically.
659
+
660
+ ## Command Routing (CRITICAL)
661
+
662
+ **You are an orchestrator — you do NOT execute code-level commands locally.** When the user invokes a WogiFlow command, route it based on this table:
663
+
664
+ | Command | Action | Why |
665
+ |---------|--------|-----|
666
+ | \`/wogi-review\` | **Dispatch to ALL workers** → aggregate findings + cross-repo analysis | Workers have the source code and full pipeline |
667
+ | \`/wogi-audit\` | **Dispatch to ALL workers** → aggregate audit results + cross-repo analysis | Same reason |
668
+ | \`/wogi-test\` | **Dispatch to ALL workers** → aggregate test results | Tests run in each repo's environment |
669
+ | \`/wogi-health\` | **Dispatch to ALL workers** → unified health report | Each repo has its own workflow state |
670
+ | \`/wogi-start "task"\` | **Analyze → decompose → dispatch** to correct worker(s) | Already designed for this |
671
+ | \`/wogi-status\` | Run **locally** — workspace-level overview | Reads workspace state files |
672
+ | \`/wogi-ready\` | Run **locally** — cross-repo task queue | Reads all repos' ready.json |
673
+ | \`/wogi-session-end\` | Run **locally** — end workspace session | Workspace-level action |
674
+
675
+ **How to dispatch a command to all workers:**
676
+ \`\`\`bash
677
+ ${Object.entries(config.channels?.members || {}).map(([name, ch]) =>
678
+ `curl -s -X POST http://localhost:${ch.port} -d "/wogi-review" # → ${name}`
679
+ ).join('\n')}
680
+ \`\`\`
681
+
682
+ **After all workers complete:** Run a cross-repo analysis that only you can do:
683
+ 1. Collect findings from \`.workspace/messages/\` (workers write results there)
684
+ 2. Check API contract alignment between provider and consumer
685
+ 3. Check for integration gaps (orphaned consumers, drifted contracts)
686
+ 4. Check shared decisions compliance (\`.workspace/state/decisions.md\`)
687
+ 5. Present unified report: per-repo findings + cross-repo findings
688
+
640
689
  ## Workspace Commands
641
690
 
642
691
  | Command | What it does |
@@ -645,6 +694,7 @@ When a provider changes an endpoint, update the contract BEFORE the consumer imp
645
694
  | \`flow workspace status\` | Show all repos, tasks, messages, contracts |
646
695
  | \`flow workspace add <path>\` | Add a new member repo |
647
696
  | \`flow workspace remove <name>\` | Remove a member repo |
697
+ | \`flow workspace start\` | Start a worker session (run from within a member repo) |
648
698
 
649
699
  ## File Reference
650
700
 
@@ -690,7 +740,13 @@ function generateWorkspaceSettings(memberNames) {
690
740
  'Bash(node --check *)',
691
741
  'Bash(node scripts/*)',
692
742
  'Bash(ls *)',
693
- 'Bash(cat *)'
743
+ 'Bash(cat *)',
744
+ 'Bash(curl http://localhost:*)',
745
+ 'Bash(curl http://127.0.0.1:*)',
746
+ 'Bash(curl -s http://localhost:*)',
747
+ 'Bash(curl -s http://127.0.0.1:*)',
748
+ 'Bash(curl -s -X POST http://localhost:*)',
749
+ 'Bash(curl -s -X POST http://127.0.0.1:*)'
694
750
  ];
695
751
 
696
752
  for (const name of (memberNames || [])) {
@@ -785,6 +841,95 @@ state/contract-versions.json
785
841
  }
786
842
  }
787
843
 
844
+ // ============================================================
845
+ // ============================================================
846
+ // Channel MCP Config Generation
847
+ // ============================================================
848
+
849
+ /**
850
+ * Generate .mcp.json for each member repo with channel server config.
851
+ * This allows workers to receive task dispatches from the manager
852
+ * and communicate with peer repos via channels.
853
+ *
854
+ * @param {string} workspaceRoot
855
+ * @param {Object} config — workspace config (with channels section)
856
+ */
857
+ function generateMemberMcpConfigs(workspaceRoot, config) {
858
+ const channelMembers = config.channels?.members || {};
859
+ const memberNames = Object.keys(channelMembers);
860
+
861
+ const VALID_NAME = /^[a-zA-Z0-9_-]{1,64}$/;
862
+
863
+ for (const [name, channelConfig] of Object.entries(channelMembers)) {
864
+ if (!VALID_NAME.test(name)) {
865
+ console.error(` ✗ ${name}: invalid member name (must match [a-zA-Z0-9_-]) — skipping`);
866
+ continue;
867
+ }
868
+
869
+ const memberPath = path.resolve(workspaceRoot, config.members[name]?.path || `./${name}`);
870
+
871
+ // Path traversal guard — ensure member path is inside workspace root
872
+ if (!memberPath.startsWith(workspaceRoot + path.sep) && memberPath !== workspaceRoot) {
873
+ console.error(` ✗ ${name}: path escapes workspace root (${config.members[name]?.path}) — skipping`);
874
+ continue;
875
+ }
876
+
877
+ const mcpJsonPath = path.join(memberPath, '.mcp.json');
878
+
879
+ // Build peer list (all other members)
880
+ const peers = memberNames
881
+ .filter(n => n !== name)
882
+ .map(n => `${n}:${channelMembers[n].port}`)
883
+ .join(',');
884
+
885
+ // Resolve channel server script path
886
+ // Use require.resolve to find the installed wogiflow package
887
+ let channelServerPath;
888
+ try {
889
+ channelServerPath = require.resolve('wogiflow/lib/workspace-channel-server.js');
890
+ } catch (_err) {
891
+ // Fallback: relative path from workspace root
892
+ channelServerPath = path.join(__dirname, 'workspace-channel-server.js');
893
+ }
894
+
895
+ const mcpConfig = {
896
+ mcpServers: {
897
+ 'wogi-workspace-channel': {
898
+ command: 'node',
899
+ args: [channelServerPath],
900
+ env: {
901
+ WOGI_CHANNEL_PORT: String(channelConfig.port),
902
+ WOGI_REPO_NAME: name,
903
+ WOGI_PEERS: peers,
904
+ WOGI_WORKSPACE_ROOT: workspaceRoot
905
+ }
906
+ }
907
+ }
908
+ };
909
+
910
+ // Merge with existing .mcp.json if present
911
+ let existingConfig = {};
912
+ try {
913
+ if (fs.existsSync(mcpJsonPath)) {
914
+ existingConfig = JSON.parse(fs.readFileSync(mcpJsonPath, 'utf-8'));
915
+ }
916
+ } catch (_err) {
917
+ // Ignore malformed existing config
918
+ }
919
+
920
+ const merged = {
921
+ ...existingConfig,
922
+ mcpServers: {
923
+ ...(existingConfig.mcpServers || {}),
924
+ ...mcpConfig.mcpServers
925
+ }
926
+ };
927
+
928
+ fs.writeFileSync(mcpJsonPath, JSON.stringify(merged, null, 2));
929
+ console.log(` ✓ ${name}/.mcp.json (channel port ${channelConfig.port}, peers: ${peers || 'none'})`);
930
+ }
931
+ }
932
+
788
933
  // ============================================================
789
934
  // Main Init Function
790
935
  // ============================================================
@@ -794,16 +939,76 @@ state/contract-versions.json
794
939
  * @param {string[]} args — CLI arguments
795
940
  */
796
941
  async function initWorkspace(args) {
797
- const workspaceRoot = process.cwd();
798
- const workspaceName = path.basename(workspaceRoot);
942
+ let workspaceRoot = process.cwd();
943
+
944
+ // Walk up to find existing workspace root (same as startWorkerSession)
945
+ let existingWorkspaceRoot = null;
946
+ let dir = workspaceRoot;
947
+ while (dir !== path.dirname(dir)) {
948
+ if (fs.existsSync(path.join(dir, WORKSPACE_CONFIG_FILE))) {
949
+ existingWorkspaceRoot = dir;
950
+ break;
951
+ }
952
+ dir = path.dirname(dir);
953
+ }
799
954
 
800
- // Check if workspace already exists
801
- if (fs.existsSync(path.join(workspaceRoot, WORKSPACE_CONFIG_FILE))) {
802
- console.error(`Workspace already initialized in ${workspaceRoot}`);
803
- console.error('Use `flow workspace sync` to update.');
955
+ // If we're inside an existing workspace (found in parent or CWD)
956
+ if (existingWorkspaceRoot) {
957
+ // Check if channels need to be enabled (upgrade path)
958
+ let existingConfig;
959
+ try {
960
+ existingConfig = JSON.parse(fs.readFileSync(path.join(existingWorkspaceRoot, WORKSPACE_CONFIG_FILE), 'utf-8'));
961
+ } catch (err) {
962
+ console.error(`Error reading workspace config: ${err.message}`);
963
+ process.exit(1);
964
+ }
965
+
966
+ if (!existingConfig.channels?.enabled) {
967
+ console.log(`Workspace found at ${existingWorkspaceRoot}`);
968
+ console.log('Channels not yet enabled — adding channel configuration...\n');
969
+
970
+ // Add channels section to existing config
971
+ const members = Object.keys(existingConfig.members);
972
+ const basePort = 8801;
973
+ existingConfig.channels = {
974
+ enabled: true,
975
+ basePort,
976
+ members: {}
977
+ };
978
+ let port = basePort;
979
+ for (const name of members) {
980
+ existingConfig.channels.members[name] = { port: port++ };
981
+ }
982
+
983
+ // Write updated config
984
+ fs.writeFileSync(
985
+ path.join(existingWorkspaceRoot, WORKSPACE_CONFIG_FILE),
986
+ JSON.stringify(existingConfig, null, 2)
987
+ );
988
+ console.log(` ✓ Updated ${WORKSPACE_CONFIG_FILE} with channels (ports ${basePort}-${basePort + members.length - 1})`);
989
+
990
+ // Generate .mcp.json for each member
991
+ console.log('');
992
+ console.log('── Setting up workspace channels ────────────\n');
993
+ generateMemberMcpConfigs(existingWorkspaceRoot, existingConfig);
994
+ console.log('');
995
+ console.log('Channels enabled! Run `flow workspace start` from a member repo to begin.');
996
+ return;
997
+ }
998
+
999
+ // Workspace exists and channels are already enabled
1000
+ if (existingWorkspaceRoot !== workspaceRoot) {
1001
+ console.error(`You are inside workspace "${path.basename(existingWorkspaceRoot)}" at ${existingWorkspaceRoot}`);
1002
+ console.error(`Run this command from the workspace root, or use \`flow workspace sync\` to update.`);
1003
+ } else {
1004
+ console.error(`Workspace already initialized in ${workspaceRoot}`);
1005
+ console.error('Use `flow workspace sync` to update.');
1006
+ }
804
1007
  process.exit(1);
805
1008
  }
806
1009
 
1010
+ const workspaceName = path.basename(workspaceRoot);
1011
+
807
1012
  console.log('🔍 Scanning for WogiFlow-enabled projects...\n');
808
1013
 
809
1014
  // Discover member repos
@@ -899,6 +1104,13 @@ async function initWorkspace(args) {
899
1104
  JSON.stringify(settings, null, 2)
900
1105
  );
901
1106
  console.log(' ✓ .claude/settings.json');
1107
+
1108
+ // Generate .mcp.json for each member repo (channel server config)
1109
+ if (config.channels?.enabled) {
1110
+ console.log('');
1111
+ console.log('── Setting up workspace channels ────────────\n');
1112
+ generateMemberMcpConfigs(workspaceRoot, config);
1113
+ }
902
1114
  console.log('');
903
1115
 
904
1116
  // Summary
@@ -981,6 +1193,122 @@ function generateIntegrationMap(manifest) {
981
1193
  return lines.join('\n');
982
1194
  }
983
1195
 
1196
+ // ============================================================
1197
+ // Worker Session Launcher
1198
+ // ============================================================
1199
+
1200
+ /**
1201
+ * Start a Claude Code worker session with the workspace channel enabled.
1202
+ * Must be run from within a member repo directory.
1203
+ *
1204
+ * @param {string} cwd — current working directory (should be a member repo)
1205
+ */
1206
+ function startWorkerSession(cwd) {
1207
+ const { execSync } = require('node:child_process');
1208
+
1209
+ // Find workspace root by walking up
1210
+ let workspaceRoot = null;
1211
+ let dir = cwd;
1212
+ while (dir !== path.dirname(dir)) {
1213
+ if (fs.existsSync(path.join(dir, WORKSPACE_CONFIG_FILE))) {
1214
+ workspaceRoot = dir;
1215
+ break;
1216
+ }
1217
+ dir = path.dirname(dir);
1218
+ }
1219
+
1220
+ if (!workspaceRoot) {
1221
+ console.error('Error: Not inside a workspace. Could not find wogi-workspace.json in any parent directory.');
1222
+ process.exit(1);
1223
+ }
1224
+
1225
+ // Read workspace config
1226
+ let config;
1227
+ try {
1228
+ config = JSON.parse(fs.readFileSync(path.join(workspaceRoot, WORKSPACE_CONFIG_FILE), 'utf-8'));
1229
+ } catch (err) {
1230
+ console.error(`Error reading workspace config: ${err.message}`);
1231
+ process.exit(1);
1232
+ }
1233
+
1234
+ if (!config.channels?.enabled) {
1235
+ console.error('Error: Channels are not enabled in this workspace. Run "flow workspace init" to set up channels.');
1236
+ process.exit(1);
1237
+ }
1238
+
1239
+ // Determine which member we are based on cwd
1240
+ const relativePath = path.relative(workspaceRoot, cwd);
1241
+ let memberName = null;
1242
+ let memberChannel = null;
1243
+
1244
+ for (const [name, memberConfig] of Object.entries(config.members)) {
1245
+ const memberRelPath = memberConfig.path.replace(/^\.\//, '');
1246
+ if (relativePath === memberRelPath || relativePath.startsWith(memberRelPath + path.sep)) {
1247
+ memberName = name;
1248
+ memberChannel = config.channels.members[name];
1249
+ break;
1250
+ }
1251
+ }
1252
+
1253
+ if (!memberName || !memberChannel) {
1254
+ console.error(`Error: Current directory "${relativePath}" does not match any workspace member.`);
1255
+ console.error('Members:', Object.keys(config.members).join(', '));
1256
+ process.exit(1);
1257
+ }
1258
+
1259
+ // Build peer list
1260
+ const peers = Object.entries(config.channels.members)
1261
+ .filter(([n]) => n !== memberName)
1262
+ .map(([n, ch]) => `${n}:${ch.port}`)
1263
+ .join(',');
1264
+
1265
+ // Verify .mcp.json exists with channel config
1266
+ const mcpJsonPath = path.join(cwd, '.mcp.json');
1267
+ let mcpConfigValid = false;
1268
+ try {
1269
+ if (fs.existsSync(mcpJsonPath)) {
1270
+ const mcpConfig = JSON.parse(fs.readFileSync(mcpJsonPath, 'utf-8'));
1271
+ mcpConfigValid = !!mcpConfig?.mcpServers?.['wogi-workspace-channel'];
1272
+ }
1273
+ } catch (_err) {
1274
+ // Malformed .mcp.json
1275
+ }
1276
+
1277
+ if (!mcpConfigValid) {
1278
+ console.error(`Error: .mcp.json missing or does not contain wogi-workspace-channel config.`);
1279
+ console.error('Run "flow workspace init" from the workspace root to generate channel configs.');
1280
+ process.exit(1);
1281
+ }
1282
+
1283
+ console.log(`Starting worker session for "${memberName}" (port ${memberChannel.port})`);
1284
+ if (peers) console.log(`Peers: ${peers}`);
1285
+ console.log('');
1286
+
1287
+ // Set up environment for the channel server
1288
+ const env = {
1289
+ ...process.env,
1290
+ WOGI_CHANNEL_PORT: String(memberChannel.port),
1291
+ WOGI_REPO_NAME: memberName,
1292
+ WOGI_PEERS: peers,
1293
+ WOGI_WORKSPACE_ROOT: workspaceRoot
1294
+ };
1295
+
1296
+ // Launch Claude Code with the channel
1297
+ try {
1298
+ execSync('claude --dangerously-load-development-channels server:wogi-workspace-channel', {
1299
+ cwd,
1300
+ env,
1301
+ stdio: 'inherit'
1302
+ });
1303
+ } catch (err) {
1304
+ // Exit code 0 or SIGINT from user quit — that's fine
1305
+ if (err.status && err.status !== 0 && err.signal !== 'SIGINT') {
1306
+ console.error(`Worker session exited with error (code ${err.status}): ${err.message}`);
1307
+ process.exit(err.status);
1308
+ }
1309
+ }
1310
+ }
1311
+
984
1312
  // ============================================================
985
1313
  // CLI Router
986
1314
  // ============================================================
@@ -1033,6 +1361,10 @@ async function workspace(args) {
1033
1361
  console.log(`✓ Removed '${name}' from workspace`);
1034
1362
  break;
1035
1363
  }
1364
+ case 'start': {
1365
+ startWorkerSession(process.cwd());
1366
+ break;
1367
+ }
1036
1368
  default:
1037
1369
  console.log(`
1038
1370
  Wogi Workspace — Multi-Repo Orchestration
@@ -1045,11 +1377,13 @@ Commands:
1045
1377
  status Show unified workspace status
1046
1378
  add Add a member repo to the workspace
1047
1379
  remove Remove a member repo from the workspace
1380
+ start Start a worker session with channel (run from a member repo)
1048
1381
 
1049
1382
  Examples:
1050
1383
  flow workspace init # Create workspace from subdirectories
1051
1384
  flow workspace sync # Refresh after external changes
1052
1385
  flow workspace status # Show all repos, tasks, contracts
1386
+ cd frontend/ && flow workspace start # Start worker session
1053
1387
  `);
1054
1388
  }
1055
1389
  }
@@ -1069,5 +1403,7 @@ module.exports = {
1069
1403
  createWorkspaceStructure,
1070
1404
  WORKSPACE_CONFIG_FILE,
1071
1405
  WORKSPACE_DIR,
1072
- MEMBER_ROLES
1406
+ MEMBER_ROLES,
1407
+ generateMemberMcpConfigs,
1408
+ startWorkerSession
1073
1409
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wogiflow",
3
- "version": "2.4.4",
3
+ "version": "2.5.1",
4
4
  "description": "AI-powered development workflow management system with multi-model support",
5
5
  "main": "lib/index.js",
6
6
  "bin": {