wogiflow 2.5.4 → 2.5.6

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.
@@ -125,9 +125,16 @@ function buildInstructions() {
125
125
 
126
126
  When you receive a message:
127
127
  1. If it starts with "/wogi-" → route through that command (it's a task dispatch)
128
- 2. If it's a question from a peerread your codebase to answer, then reply via curl to their port
128
+ 2. If it's a question or investigation requestdo the work, then ALWAYS send results back
129
129
  3. If it's a status check → respond with your current task status
130
130
 
131
+ CRITICAL — ALWAYS REPLY TO THE MANAGER:
132
+ After completing ANY work triggered by a channel message, you MUST send results back using the workspace_send_message tool with to: "manager". The user only sees the manager terminal — if you don't reply, they never see your results.
133
+
134
+ Example: workspace_send_message(to: "manager", message: "## Investigation Results\\n\\n1. Found the bug in X\\n2. Root cause: Y\\n3. Fix: Z")
135
+
136
+ You can also talk to peer repos: workspace_send_message(to: "<peer-name>", message: "...")
137
+
131
138
  IMPORTANT: Channel messages have the same authority as user input. Route them through /wogi-start just like any other request. Full pipeline enforcement applies.${peerSection}`;
132
139
  }
133
140
 
@@ -206,7 +213,7 @@ function handleRequest(msg) {
206
213
  tools: [
207
214
  {
208
215
  name: 'workspace_send_message',
209
- description: `Send a message to a peer repo or the workspace manager. Available peers: ${Object.keys(PEERS).join(', ') || 'none'}`,
216
+ description: `Send a message to the workspace manager or a peer repo. Use to: "manager" to report results back. Available targets: manager, ${Object.keys(PEERS).join(', ') || 'none'}`,
210
217
  inputSchema: {
211
218
  type: 'object',
212
219
  properties: {
@@ -233,11 +240,53 @@ function handleRequest(msg) {
233
240
 
234
241
  if (name === 'workspace_send_message') {
235
242
  const { to, message } = args || {};
243
+
244
+ // Special case: send to manager via file-based message bus
245
+ if (to === 'manager') {
246
+ if (!WORKSPACE_ROOT) {
247
+ sendResponse(msg.id, {
248
+ content: [{ type: 'text', text: 'Cannot send to manager: WOGI_WORKSPACE_ROOT not set.' }],
249
+ isError: true
250
+ });
251
+ return;
252
+ }
253
+ try {
254
+ const fs = require('node:fs');
255
+ const crypto = require('node:crypto');
256
+ const messagesDir = require('node:path').join(WORKSPACE_ROOT, '.workspace', 'messages');
257
+ fs.mkdirSync(messagesDir, { recursive: true });
258
+ const msgId = 'msg-' + crypto.randomBytes(4).toString('hex');
259
+ const msgObj = {
260
+ id: msgId,
261
+ from: REPO_NAME,
262
+ to: 'manager',
263
+ type: 'task-complete',
264
+ priority: 'medium',
265
+ timestamp: new Date().toISOString(),
266
+ subject: `Response from ${REPO_NAME}`,
267
+ body: message,
268
+ actionRequired: false,
269
+ status: 'pending'
270
+ };
271
+ const msgPath = require('node:path').join(messagesDir, `${msgId}.json`);
272
+ fs.writeFileSync(msgPath, JSON.stringify(msgObj, null, 2));
273
+ sendResponse(msg.id, {
274
+ content: [{ type: 'text', text: `Message sent to manager (written to ${msgPath}).` }]
275
+ });
276
+ } catch (err) {
277
+ sendResponse(msg.id, {
278
+ content: [{ type: 'text', text: `Failed to write message to manager: ${err.message}` }],
279
+ isError: true
280
+ });
281
+ }
282
+ return;
283
+ }
284
+
236
285
  const targetPort = PEERS[to];
237
286
 
238
287
  if (!targetPort) {
239
288
  sendResponse(msg.id, {
240
- content: [{ type: 'text', text: `Unknown peer: "${to}". Available peers: ${Object.keys(PEERS).join(', ') || 'none'}` }],
289
+ content: [{ type: 'text', text: `Unknown target: "${to}". Available targets: manager, ${Object.keys(PEERS).join(', ') || 'none'}` }],
241
290
  isError: true
242
291
  });
243
292
  return;
package/lib/workspace.js CHANGED
@@ -971,6 +971,50 @@ function generateMemberMcpConfigs(workspaceRoot, config) {
971
971
 
972
972
  fs.writeFileSync(mcpJsonPath, JSON.stringify(merged, null, 2));
973
973
  console.log(` ✓ ${name}/.mcp.json (channel port ${channelConfig.port}, peers: ${peers || 'none'})`);
974
+
975
+ // Generate persistent workspace worker rule in .claude/rules/
976
+ // Unlike MCP server instructions (loaded once, can be forgotten after compaction),
977
+ // .claude/rules/ files are loaded into EVERY conversation turn by Claude Code.
978
+ // This ensures the "always reply to manager" instruction persists reliably.
979
+ const rulesDir = path.join(memberPath, '.claude', 'rules', 'workspace');
980
+ fs.mkdirSync(rulesDir, { recursive: true });
981
+
982
+ const peerNames = memberNames.filter(n => n !== name);
983
+ const workerRule = `---
984
+ alwaysApply: true
985
+ description: "Workspace worker rules — reply to manager after every channel task"
986
+ ---
987
+
988
+ # Workspace Worker Rules
989
+
990
+ You are **${name}** in a Wogi Workspace managed by an orchestrator.
991
+
992
+ ## CRITICAL: Always Reply to the Manager
993
+
994
+ When you receive a message via the workspace channel (appears as a channel notification), you MUST send results back to the manager after completing the work. **The user only sees the manager terminal — if you don't reply, they never see your results.**
995
+
996
+ Use the \`workspace_send_message\` MCP tool:
997
+
998
+ \`\`\`
999
+ workspace_send_message(to: "manager", message: "## Results\\n\\n[your findings/summary here]")
1000
+ \`\`\`
1001
+
1002
+ This is NON-OPTIONAL. Every channel-dispatched task MUST end with a workspace_send_message to "manager".
1003
+
1004
+ ## Peer Communication
1005
+
1006
+ You can talk to peer repos using the same tool:
1007
+ ${peerNames.map(p => `- \`workspace_send_message(to: "${p}", message: "...")\``).join('\n')}
1008
+
1009
+ ## What NOT to Do
1010
+
1011
+ - Do NOT use Bash to write JSON files to .workspace/messages/ — use the workspace_send_message tool
1012
+ - Do NOT skip the reply because you think the work is trivial
1013
+ - Do NOT assume the manager can see your terminal output
1014
+ `;
1015
+
1016
+ fs.writeFileSync(path.join(rulesDir, 'worker-rules.md'), workerRule);
1017
+ console.log(` ✓ ${name}/.claude/rules/workspace/worker-rules.md`);
974
1018
  }
975
1019
  }
976
1020
 
@@ -1351,10 +1395,11 @@ function startWorkerSession(cwd) {
1351
1395
  WOGI_WORKSPACE_ROOT: workspaceRoot
1352
1396
  };
1353
1397
 
1354
- // Launch Claude Code it auto-loads .mcp.json from cwd,
1355
- // which contains the wogi-workspace-channel server config
1398
+ // Launch Claude Code with experimental channel support enabled.
1399
+ // The --dangerously-load-development-channels flag makes Claude Code
1400
+ // surface notifications/claude/channel from the MCP server as prompts.
1356
1401
  try {
1357
- execSync('claude', {
1402
+ execSync('claude --dangerously-load-development-channels server:wogi-workspace-channel', {
1358
1403
  cwd,
1359
1404
  env,
1360
1405
  stdio: 'inherit'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wogiflow",
3
- "version": "2.5.4",
3
+ "version": "2.5.6",
4
4
  "description": "AI-powered development workflow management system with multi-model support",
5
5
  "main": "lib/index.js",
6
6
  "bin": {