orchestrix-yuri 4.8.4 → 4.8.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.
|
@@ -679,10 +679,17 @@ class PhaseOrchestrator {
|
|
|
679
679
|
this._lastActiveAgent = progress.currentAgent;
|
|
680
680
|
}
|
|
681
681
|
|
|
682
|
-
// Check if all stories done
|
|
682
|
+
// Check if all stories done — but ONLY if no agent is actively working.
|
|
683
|
+
// If an agent is busy (e.g., SM drafting new stories), story counts are stale.
|
|
683
684
|
if (progress.totalStories > 0 && progress.doneStories >= progress.totalStories) {
|
|
684
|
-
|
|
685
|
-
|
|
685
|
+
if (progress.currentAgent) {
|
|
686
|
+
// Agent still working — stories may be in flux (new ones being created)
|
|
687
|
+
log.engine(`All ${progress.doneStories}/${progress.totalStories} stories done but ${progress.currentAgent} is still active — waiting`);
|
|
688
|
+
} else {
|
|
689
|
+
// No active agent + all stories done → truly complete
|
|
690
|
+
this._completeDev();
|
|
691
|
+
return;
|
|
692
|
+
}
|
|
686
693
|
}
|
|
687
694
|
|
|
688
695
|
// Periodic progress report
|
package/lib/gateway/router.js
CHANGED
|
@@ -38,7 +38,7 @@ const META_COMMANDS = {
|
|
|
38
38
|
// All natural language ("怎么样了", "进度如何") goes through dispatcher
|
|
39
39
|
// so Claude's understanding ability decides the routing.
|
|
40
40
|
const STATUS_PATTERNS = [
|
|
41
|
-
|
|
41
|
+
/^[*/]status\b/i,
|
|
42
42
|
];
|
|
43
43
|
|
|
44
44
|
/**
|
|
@@ -307,6 +307,30 @@ class Router {
|
|
|
307
307
|
log.router(`Dispatcher unavailable, defaulting to change for: "${msg.text.slice(0, 50)}..."`);
|
|
308
308
|
}
|
|
309
309
|
|
|
310
|
+
// Context-aware override: if user sends a short confirmation and context
|
|
311
|
+
// clearly suggests a specific phase action, override dispatcher's classification.
|
|
312
|
+
if (classified.action === 'change' && lastReply) {
|
|
313
|
+
const userText = msg.text.trim().toLowerCase();
|
|
314
|
+
const isConfirmation = /^(启动|开始|go|ok|好|好的|批准|确认|start|begin|launch|yes|可以|干吧|搞起|冲|执行)$/i.test(userText)
|
|
315
|
+
|| userText.length <= 6;
|
|
316
|
+
if (isConfirmation) {
|
|
317
|
+
const ctx = lastReply.toLowerCase();
|
|
318
|
+
if (ctx.includes('启动开发') || ctx.includes('start dev') || ctx.includes('*develop') || ctx.includes('开始开发') || ctx.includes('agent') && ctx.includes('开始工作')) {
|
|
319
|
+
classified.action = 'develop';
|
|
320
|
+
classified.reasoning = 'confirmation of dev-start suggestion from context';
|
|
321
|
+
log.router(`Override: change → develop (user confirmed dev-start from context)`);
|
|
322
|
+
} else if (ctx.includes('*test') || ctx.includes('运行测试') || ctx.includes('冒烟测试')) {
|
|
323
|
+
classified.action = 'test';
|
|
324
|
+
classified.reasoning = 'confirmation of test suggestion from context';
|
|
325
|
+
log.router(`Override: change → test (user confirmed test from context)`);
|
|
326
|
+
} else if (ctx.includes('*deploy') || ctx.includes('部署') || ctx.includes('上线')) {
|
|
327
|
+
classified.action = 'deploy';
|
|
328
|
+
classified.reasoning = 'confirmation of deploy suggestion from context';
|
|
329
|
+
log.router(`Override: change → deploy (user confirmed deploy from context)`);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
|
|
310
334
|
if (classified.action !== 'conversation') {
|
|
311
335
|
try {
|
|
312
336
|
const intentResult = await this._executeClassifiedIntent(classified, msg);
|
|
@@ -628,10 +652,24 @@ Reply with ONLY one word: small, medium, or large. Nothing else.`;
|
|
|
628
652
|
try {
|
|
629
653
|
const focus = yaml.load(fs.readFileSync(focusPath, 'utf8')) || {};
|
|
630
654
|
|
|
631
|
-
|
|
655
|
+
// Always check for live dev session first — it's the ground truth.
|
|
656
|
+
// focus.yaml may be stale (e.g., still says phase 4 after dev restarted).
|
|
657
|
+
let hasLiveDevSession = false;
|
|
658
|
+
try {
|
|
659
|
+
const { execSync } = require('child_process');
|
|
660
|
+
const sessions = execSync('tmux list-sessions -F "#{session_name}" 2>/dev/null', { encoding: 'utf8' }).trim();
|
|
661
|
+
const projectName = path.basename(projectRoot).toLowerCase();
|
|
662
|
+
const devSession = sessions.split('\n').find((s) =>
|
|
663
|
+
s.startsWith('orchestrix-') && s.toLowerCase().includes(projectName)
|
|
664
|
+
) || sessions.split('\n').find((s) => s.startsWith('orchestrix-'));
|
|
665
|
+
if (devSession) {
|
|
666
|
+
const tmx = require('./engine/tmux-utils');
|
|
667
|
+
hasLiveDevSession = tmx.hasSession(devSession);
|
|
668
|
+
}
|
|
669
|
+
} catch { /* no tmux */ }
|
|
632
670
|
|
|
633
|
-
//
|
|
634
|
-
if (
|
|
671
|
+
// If live dev session exists, show dev progress card regardless of focus.yaml phase
|
|
672
|
+
if (hasLiveDevSession) {
|
|
635
673
|
try {
|
|
636
674
|
const card = this._buildStatusCard(projectRoot, focus);
|
|
637
675
|
if (card) parts.push(card);
|
|
@@ -640,8 +678,10 @@ Reply with ONLY one word: small, medium, or large. Nothing else.`;
|
|
|
640
678
|
}
|
|
641
679
|
}
|
|
642
680
|
|
|
643
|
-
|
|
644
|
-
|
|
681
|
+
const phaseNum = parseInt(focus.phase, 10);
|
|
682
|
+
|
|
683
|
+
// Test phase: only show if no live dev session and no card yet
|
|
684
|
+
if (phaseNum === 4 && parts.length === 0 && !hasLiveDevSession) {
|
|
645
685
|
try {
|
|
646
686
|
const card = this._buildTestStatusCard(projectRoot);
|
|
647
687
|
if (card) parts.push(card);
|
package/package.json
CHANGED
|
@@ -7,15 +7,15 @@ Messages may include "[CONTEXT]" with the previous assistant response for refere
|
|
|
7
7
|
|
|
8
8
|
| Action | When to use | Examples |
|
|
9
9
|
|--------|-------------|---------|
|
|
10
|
-
| bugfix | User reports a bug, error, or specific problem that needs fixing | "这个 bug 修一下", "Fix the login error", "页面报错了", "按钮点了没反应"
|
|
11
|
-
| change | User wants work done: modify, add, redesign, create a plan, write something
|
|
12
|
-
| plan | User
|
|
13
|
-
| develop | User
|
|
14
|
-
| test | User wants to run tests | "跑一下测试", "冒烟测试" |
|
|
10
|
+
| bugfix | User reports a bug, error, or specific problem that needs fixing | "这个 bug 修一下", "Fix the login error", "页面报错了", "按钮点了没反应" |
|
|
11
|
+
| change | User wants NEW work done: modify, add, redesign, create a plan, write something | "让 UX 重新设计界面", "Add dark mode", "写一份方案" |
|
|
12
|
+
| plan | User wants to start or restart planning | "开始规划", "*plan", "重新规划" |
|
|
13
|
+
| develop | User wants to start, resume, or continue development | "开始开发", "*develop", "启动开发", "继续开发", "让 Agent 开始工作" |
|
|
14
|
+
| test | User wants to run tests | "跑一下测试", "冒烟测试", "*test" |
|
|
15
15
|
| deploy | User wants to deploy or release | "部署到线上", "发布", "上线" |
|
|
16
|
-
| status | User asks about progress
|
|
16
|
+
| status | User asks about progress or what happened | "进展如何?", "怎么样了", "结果出来了吗" |
|
|
17
17
|
| iterate | User wants a new iteration cycle | "新迭代", "下一轮" |
|
|
18
|
-
| conversation | ONLY for pure questions or opinions with NO actionable request | "你觉得怎么样?", "
|
|
18
|
+
| conversation | ONLY for pure questions or opinions with NO actionable request | "你觉得怎么样?", "解释一下这段代码" |
|
|
19
19
|
|
|
20
20
|
## Response Format
|
|
21
21
|
|
|
@@ -23,14 +23,31 @@ Reply with EXACTLY this JSON format on a single line, nothing else:
|
|
|
23
23
|
|
|
24
24
|
{"action":"<action>","description":"<brief description for the agent>","reasoning":"<one sentence why>"}
|
|
25
25
|
|
|
26
|
-
## Critical Rules
|
|
26
|
+
## Critical Rules (read ALL before classifying)
|
|
27
|
+
|
|
28
|
+
### Rule 1: CONTEXT determines the action for confirmations
|
|
29
|
+
If the user sends a short confirmation ("启动", "ok", "开始", "go", "批准", "好的", "确认"), look at [CONTEXT] to determine WHAT they're confirming:
|
|
30
|
+
- Context mentions starting development/coding → "develop"
|
|
31
|
+
- Context mentions running tests → "test"
|
|
32
|
+
- Context mentions deploying → "deploy"
|
|
33
|
+
- Context mentions planning → "plan"
|
|
34
|
+
- Context mentions a specific change/redesign → "change"
|
|
35
|
+
- No clear context → "change" (default)
|
|
36
|
+
|
|
37
|
+
### Rule 2: Bug vs Change
|
|
38
|
+
Bug, error, problem, something broken → "bugfix". New work, redesign, feature → "change".
|
|
39
|
+
|
|
40
|
+
### Rule 3: Bias toward action
|
|
41
|
+
If the user wants ANYTHING done, classify as an action (change/bugfix/develop/test/etc). Never let work requests fall into "conversation".
|
|
42
|
+
|
|
43
|
+
### Rule 4: Agent references
|
|
44
|
+
If the user names an agent (UX, architect, PM, dev, SM, QA) and wants them to do something → "change".
|
|
45
|
+
|
|
46
|
+
### Rule 5: "conversation" is rare
|
|
47
|
+
Only for messages that require NO action — pure questions, opinions, greetings. When in doubt, prefer an action.
|
|
48
|
+
|
|
49
|
+
### Rule 6: "develop" is broader than you think
|
|
50
|
+
Any of these mean "develop": 启动, 开始干活, 让他们工作, 跑起来, 开工, start working, begin, launch, kick off development. If user wants agents to start executing stories → "develop".
|
|
27
51
|
|
|
28
|
-
- **Bug vs Change**: If the user reports a bug, error, problem, or something broken → "bugfix". If the user wants new work, redesign, or feature → "change". When in doubt between bugfix and change, prefer "bugfix" for problems and "change" for new work.
|
|
29
|
-
- **Bias toward action**: If the user wants ANYTHING done (create, write, fix, modify, redesign, evaluate, plan something), classify as "change" or "bugfix". Never let work requests fall into "conversation".
|
|
30
|
-
- If the user is replying to a question with a choice/decision (e.g., "先做 plan" answering "要 A 还是 B?"), that reply IS an instruction — classify as "change", NOT "conversation".
|
|
31
|
-
- If the user references a specific agent role (UX, UI, architect, PM, QA, dev, SM) and wants them to do something, classify as "change".
|
|
32
|
-
- If the user asks about previous results, output, or progress, classify as "status".
|
|
33
|
-
- "conversation" is ONLY for messages that require NO action at all — pure questions, opinions, greetings.
|
|
34
|
-
- When in doubt between "change" and "conversation", ALWAYS choose "change".
|
|
35
52
|
- The "description" field should be a concise summary of what the user wants done.
|
|
36
53
|
- ALWAYS respond with the JSON format above. Never add explanation, markdown, or anything else.
|