u-foo 1.8.8 → 1.8.9

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "u-foo",
3
- "version": "1.8.8",
3
+ "version": "1.8.9",
4
4
  "description": "Multi-Agent Workspace Protocol. Just add u. claude → uclaude, codex → ucodex.",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "homepage": "https://ufoo.dev",
@@ -37,6 +37,40 @@ async function connectWithRetry(sockPath, retries, delayMs) {
37
37
  return null;
38
38
  }
39
39
 
40
+ async function notifyDaemonAgentReady(daemonSockPath, subscriberId, agentPid) {
41
+ if (!daemonSockPath || !subscriberId) return false;
42
+ const parsedAgentPid = Number.parseInt(agentPid, 10);
43
+ if (!Number.isFinite(parsedAgentPid) || parsedAgentPid <= 0) return false;
44
+
45
+ const startTime = Date.now();
46
+ try {
47
+ const daemonSock = await connectWithRetry(daemonSockPath, 3, 100);
48
+ if (!daemonSock) {
49
+ if (process.env.UFOO_DEBUG) {
50
+ console.error("[ready] failed to connect to daemon after retries, will use fallback delay");
51
+ }
52
+ return false;
53
+ }
54
+
55
+ daemonSock.write(`${JSON.stringify({
56
+ type: IPC_REQUEST_TYPES.AGENT_READY,
57
+ subscriberId,
58
+ agentPid: parsedAgentPid,
59
+ })}\n`);
60
+ daemonSock.end();
61
+
62
+ if (process.env.UFOO_DEBUG) {
63
+ console.error(`[ready] notified daemon in ${Date.now() - startTime}ms`);
64
+ }
65
+ return true;
66
+ } catch (err) {
67
+ if (process.env.UFOO_DEBUG) {
68
+ console.error(`[ready] daemon notification error: ${err.message}, will use fallback delay`);
69
+ }
70
+ return false;
71
+ }
72
+ }
73
+
40
74
  async function probeDaemonSocket(sockPath) {
41
75
  try {
42
76
  const client = await connectSocket(sockPath);
@@ -497,6 +531,11 @@ class AgentLauncher {
497
531
  },
498
532
  });
499
533
 
534
+ if (resolveLaunchMode() === "host" && child.pid) {
535
+ const daemonSockPath = getUfooPaths(this.cwd).ufooSock;
536
+ notifyDaemonAgentReady(daemonSockPath, subscriberId, child.pid).catch(() => {});
537
+ }
538
+
500
539
  child.on("error", (err) => {
501
540
  console.error(`[${this.command}] Failed to start:`, err.message);
502
541
  process.exit(1);
@@ -665,33 +704,7 @@ class AgentLauncher {
665
704
  }
666
705
  }
667
706
 
668
- const startTime = Date.now();
669
- try {
670
- const daemonSock = await connectWithRetry(daemonSockPath, 3, 100);
671
- if (daemonSock) {
672
- daemonSock.write(`${JSON.stringify({
673
- type: IPC_REQUEST_TYPES.AGENT_READY,
674
- subscriberId,
675
- agentPid: wrapper.pty ? wrapper.pty.pid : 0,
676
- })}\n`);
677
- daemonSock.end();
678
-
679
- const notifyTime = Date.now() - startTime;
680
- if (process.env.UFOO_DEBUG) {
681
- console.error(`[ready] notified daemon in ${notifyTime}ms`);
682
- }
683
- } else {
684
- if (process.env.UFOO_DEBUG) {
685
- console.error(`[ready] failed to connect to daemon after retries, will use fallback delay`);
686
- }
687
- }
688
- } catch (err) {
689
- // 忽略通知失败(probe会通过fallback延迟执行)
690
- if (process.env.UFOO_DEBUG) {
691
- console.error(`[ready] daemon notification error: ${err.message}, will use fallback delay`);
692
- }
693
- }
694
-
707
+ await notifyDaemonAgentReady(daemonSockPath, subscriberId, wrapper.pty ? wrapper.pty.pid : 0);
695
708
  });
696
709
 
697
710
  // Fallback:如果10秒后还没检测到ready,强制标记为ready
@@ -938,5 +951,6 @@ class AgentLauncher {
938
951
  // Exported for testing
939
952
  AgentLauncher._sanitizeNickname = (nick) => nick.replace(/[^a-zA-Z0-9_-]/g, "");
940
953
  AgentLauncher._findPreviousSession = findPreviousSession;
954
+ AgentLauncher._notifyDaemonAgentReady = notifyDaemonAgentReady;
941
955
 
942
956
  module.exports = AgentLauncher;
@@ -352,6 +352,38 @@ const BUILTIN_PROFILES = [
352
352
  "- Use `ufoo bus send <target-nickname> \"<message>\"` to deliver handoffs to other agents.",
353
353
  ].join("\n"),
354
354
  },
355
+ {
356
+ id: "pmo-coordinator",
357
+ display_name: "PMO",
358
+ short_name: "PMO",
359
+ aliases: ["pmo"],
360
+ summary: "Coordinate execution across builders, track progress, unblock dependencies, and enforce delivery cadence.",
361
+ prompt: [
362
+ "You are the PMO coordinator for this ufoo group.",
363
+ "",
364
+ "Mission:",
365
+ "- Coordinate execution across multiple builders to maximize throughput and minimize idle time.",
366
+ "- Track progress, surface blockers early, enforce delivery cadence, and keep the team aligned on priorities.",
367
+ "",
368
+ "Boundaries:",
369
+ "- Do not make architectural or scope decisions — escalate to architect or scope challenger.",
370
+ "- Do not write production code.",
371
+ "- Do not reorder priorities without naming the tradeoff and notifying affected agents.",
372
+ "",
373
+ "Method:",
374
+ "- Assign slices to builders based on dependency order and current load.",
375
+ "- Monitor builder progress and proactively unblock stalled work.",
376
+ "- Maintain a clear view of what is done, in-flight, and blocked at all times.",
377
+ "- Enforce review gates — no slice ships without reviewer sign-off.",
378
+ "- Batch related changes when possible to reduce review churn.",
379
+ "",
380
+ "Handoff:",
381
+ "- Send execution-ready slices to builders with clear acceptance criteria.",
382
+ "- Send completed work to reviewer with context on what changed and why.",
383
+ "- Escalate blockers to architect or the human operator.",
384
+ "- Use `ufoo bus send <target-nickname> \"<message>\"` to deliver handoffs to other agents.",
385
+ ].join("\n"),
386
+ },
355
387
  {
356
388
  id: "rapid-prototype",
357
389
  display_name: "Prototype",
@@ -0,0 +1,219 @@
1
+ {
2
+ "schema_version": 1,
3
+ "template": {
4
+ "id": "build-ultra",
5
+ "alias": "build-ultra",
6
+ "name": "Build Ultra"
7
+ },
8
+ "defaults": {
9
+ "launch_mode": "auto",
10
+ "start_timeout_ms": 15000
11
+ },
12
+ "agents": [
13
+ {
14
+ "id": "pmo",
15
+ "nickname": "pmo",
16
+ "type": "auto",
17
+ "role": "coordinate builders, track progress, enforce delivery cadence",
18
+ "prompt_profile": "pmo-coordinator",
19
+ "accept_from": [],
20
+ "report_to": [
21
+ "builder-1",
22
+ "builder-2",
23
+ "builder-3",
24
+ "builder-4",
25
+ "reviewer"
26
+ ],
27
+ "startup_order": 1,
28
+ "depends_on": []
29
+ },
30
+ {
31
+ "id": "builder-1",
32
+ "nickname": "builder-1",
33
+ "type": "auto",
34
+ "role": "implement approved slices",
35
+ "prompt_profile": "implementation-lead",
36
+ "accept_from": [
37
+ "pmo",
38
+ "reviewer"
39
+ ],
40
+ "report_to": [
41
+ "pmo",
42
+ "reviewer"
43
+ ],
44
+ "startup_order": 2,
45
+ "depends_on": [
46
+ "pmo"
47
+ ]
48
+ },
49
+ {
50
+ "id": "builder-2",
51
+ "nickname": "builder-2",
52
+ "type": "auto",
53
+ "role": "implement approved slices",
54
+ "prompt_profile": "implementation-lead",
55
+ "accept_from": [
56
+ "pmo",
57
+ "reviewer"
58
+ ],
59
+ "report_to": [
60
+ "pmo",
61
+ "reviewer"
62
+ ],
63
+ "startup_order": 2,
64
+ "depends_on": [
65
+ "pmo"
66
+ ]
67
+ },
68
+ {
69
+ "id": "builder-3",
70
+ "nickname": "builder-3",
71
+ "type": "auto",
72
+ "role": "implement approved slices",
73
+ "prompt_profile": "implementation-lead",
74
+ "accept_from": [
75
+ "pmo",
76
+ "reviewer"
77
+ ],
78
+ "report_to": [
79
+ "pmo",
80
+ "reviewer"
81
+ ],
82
+ "startup_order": 2,
83
+ "depends_on": [
84
+ "pmo"
85
+ ]
86
+ },
87
+ {
88
+ "id": "builder-4",
89
+ "nickname": "builder-4",
90
+ "type": "auto",
91
+ "role": "implement approved slices",
92
+ "prompt_profile": "implementation-lead",
93
+ "accept_from": [
94
+ "pmo",
95
+ "reviewer"
96
+ ],
97
+ "report_to": [
98
+ "pmo",
99
+ "reviewer"
100
+ ],
101
+ "startup_order": 2,
102
+ "depends_on": [
103
+ "pmo"
104
+ ]
105
+ },
106
+ {
107
+ "id": "reviewer",
108
+ "nickname": "reviewer",
109
+ "type": "auto",
110
+ "role": "review correctness and risk",
111
+ "prompt_profile": "review-critic",
112
+ "accept_from": [
113
+ "pmo",
114
+ "builder-1",
115
+ "builder-2",
116
+ "builder-3",
117
+ "builder-4"
118
+ ],
119
+ "report_to": [
120
+ "pmo",
121
+ "builder-1",
122
+ "builder-2",
123
+ "builder-3",
124
+ "builder-4"
125
+ ],
126
+ "startup_order": 3,
127
+ "depends_on": [
128
+ "pmo"
129
+ ]
130
+ }
131
+ ],
132
+ "edges": [
133
+ {
134
+ "from": "pmo",
135
+ "to": "builder-1",
136
+ "kind": "task"
137
+ },
138
+ {
139
+ "from": "pmo",
140
+ "to": "builder-2",
141
+ "kind": "task"
142
+ },
143
+ {
144
+ "from": "pmo",
145
+ "to": "builder-3",
146
+ "kind": "task"
147
+ },
148
+ {
149
+ "from": "pmo",
150
+ "to": "builder-4",
151
+ "kind": "task"
152
+ },
153
+ {
154
+ "from": "builder-1",
155
+ "to": "reviewer",
156
+ "kind": "review"
157
+ },
158
+ {
159
+ "from": "builder-2",
160
+ "to": "reviewer",
161
+ "kind": "review"
162
+ },
163
+ {
164
+ "from": "builder-3",
165
+ "to": "reviewer",
166
+ "kind": "review"
167
+ },
168
+ {
169
+ "from": "builder-4",
170
+ "to": "reviewer",
171
+ "kind": "review"
172
+ },
173
+ {
174
+ "from": "reviewer",
175
+ "to": "builder-1",
176
+ "kind": "task"
177
+ },
178
+ {
179
+ "from": "reviewer",
180
+ "to": "builder-2",
181
+ "kind": "task"
182
+ },
183
+ {
184
+ "from": "reviewer",
185
+ "to": "builder-3",
186
+ "kind": "task"
187
+ },
188
+ {
189
+ "from": "reviewer",
190
+ "to": "builder-4",
191
+ "kind": "task"
192
+ },
193
+ {
194
+ "from": "reviewer",
195
+ "to": "pmo",
196
+ "kind": "report"
197
+ },
198
+ {
199
+ "from": "builder-1",
200
+ "to": "pmo",
201
+ "kind": "report"
202
+ },
203
+ {
204
+ "from": "builder-2",
205
+ "to": "pmo",
206
+ "kind": "report"
207
+ },
208
+ {
209
+ "from": "builder-3",
210
+ "to": "pmo",
211
+ "kind": "report"
212
+ },
213
+ {
214
+ "from": "builder-4",
215
+ "to": "pmo",
216
+ "kind": "report"
217
+ }
218
+ ]
219
+ }